find
Поиск файлов и директорий по критериям с возможностью выполнения действий
Описание
find — мощная утилита поиска файлов в файловой системе по множеству критериев: имени,
типу, размеру, правам доступа, дате модификации, владельцу и другим атрибутам. Команда обходит
дерево каталогов начиная с указанной точки и проверяет каждый файл против набора выражений-фильтров.
Главное отличие find от простого glob-поиска оболочки — возможность поиска по множеству
критериев одновременно, рекурсивность, поиск по метаданным (размер, дата, права), а главное —
возможность немедленно выполнить действие с найденным файлом через флаг -exec или
-delete. Это делает find незаменимым инструментом системного администратора.
Синтаксис find необычен для командной строки Unix — он больше похож на язык запросов
с операторами И (-a), ИЛИ (-o) и отрицанием (!). Выражения
вычисляются слева направо с поддержкой скобок. Это позволяет строить сложные составные условия поиска.
Синтаксис
- ПУТЬ — начальная точка поиска (по умолчанию
.— текущая директория) - ВЫРАЖЕНИЕ — цепочка тестов, операторов и действий
Структура выражения:
Флаги и опции
Глобальные опции
| Флаг | Описание | Пример |
|---|---|---|
-maxdepth N |
Ограничить глубину обхода N уровнями (0 = только стартовая точка) | find . -maxdepth 2 -name "*.py" |
-mindepth N |
Не проверять файлы на глубине меньше N | find . -mindepth 1 -maxdepth 1 |
-depth |
Обрабатывать содержимое директории перед самой директорией | find . -depth -name "*.tmp" -delete |
-follow |
Следовать по символическим ссылкам | find -L /etc -name "*.conf" |
-L |
Разыменовывать символические ссылки при обходе | find -L . -type f |
Тесты (фильтры)
| Тест | Описание | Пример |
|---|---|---|
-name ШАБЛОН |
Имя файла совпадает с шаблоном (glob, регистрозависимый) | -name "*.py" |
-iname ШАБЛОН |
Как -name, но регистронезависимый |
-iname "readme*" |
-type T |
Тип: f=файл, d=директория, l=симлинк, b=блочное, c=символьное |
-type f, -type d |
-size [+/-]N[cwbkMG] |
Размер файла: +=больше, -=меньше; единицы: k=кБ, M=МБ, G=ГБ |
-size +100M, -size -1k |
-mtime [+/-]N |
Время модификации: N дней назад (+N=старше N дней, -N=моложе N дней) |
-mtime -7, -mtime +30 |
-newer ФАЙЛ |
Файл изменён позже, чем указанный ФАЙЛ-эталон | -newer index.html |
-perm MODE |
Права доступа файла точно совпадают с MODE (восьмеричный) | -perm 777, -perm /u+x |
-user ИМЯ |
Файл принадлежит пользователю с указанным именем или UID | -user www-data |
-group ИМЯ |
Файл принадлежит указанной группе | -group developers |
-empty |
Файл или директория пустая | -type f -empty |
Действия
| Действие | Описание | Пример |
|---|---|---|
-print |
Вывести путь к файлу (поведение по умолчанию) | find . -name "*.py" -print |
-print0 |
Вывести путь с нулевым байтом-разделителем (безопасно для имён с пробелами) | find . -print0 | xargs -0 rm |
-delete |
Удалить найденный файл (подразумевает -depth) | find . -name "*.pyc" -delete |
-exec CMD {} \; |
Выполнить команду для каждого найденного файла ({} = путь к файлу) |
-exec chmod 644 {} \; |
-exec CMD {} + |
Выполнить команду, передав все найденные файлы аргументами разом (эффективнее) | -exec ls -la {} + |
-ls |
Вывести подробную информацию о файле в формате ls -dils |
find . -name "*.conf" -ls |
Паттерны использования
Найти файлы по имени
# По расширению find /var/log -name "*.log" # Регистронезависимо find ~ -iname "readme*" # Только файлы (не директории) find . -type f -name "*.py"
Базовый поиск по имени. Флаг -type f исключает директории с таким же расширением.
Найти и удалить временные файлы
# Удалить скомпилированные Python-файлы find . -name "*.pyc" -delete find . -name "__pycache__" -type d -delete # Удалить файлы старше 30 дней find /tmp -type f -mtime +30 -delete
Флаг -delete — безопаснее, чем -exec rm: он атомарен и не создаёт отдельный процесс.
Найти крупные файлы
# Файлы крупнее 100 МБ
find / -type f -size +100M 2>/dev/null
# Топ-10 крупнейших файлов
find / -type f -size +50M -exec ls -lh {} + 2>/dev/null \
| sort -k5 -rh | head -10
Полезно для ревизии дискового пространства. 2>/dev/null подавляет ошибки доступа.
Найти и выполнить действие (-exec)
# Изменить права всех .sh файлов
find . -name "*.sh" -exec chmod +x {} \;
# Заменить владельца
find /var/www -type f -exec chown www-data:www-data {} +
# Скопировать найденные файлы
find . -name "*.conf" -exec cp {} /backup/ \;
{} + передаёт все файлы за один вызов команды — быстрее, чем {} \; (отдельный вызов на каждый файл).
Поиск по дате модификации
# Изменённые за последние 7 дней find . -type f -mtime -7 # Изменённые более 30 дней назад find /var/log -name "*.log" -mtime +30 # Изменённые сегодня find . -daystart -mtime -1 # Новее, чем файл-эталон find . -newer package.json -type f
Временные критерии указываются в днях. Дробные дни задаются через -mmin (в минутах).
Поиск по правам доступа
# Файлы с setuid find / -perm /4000 -type f 2>/dev/null # Файлы доступные на запись всем (небезопасно) find / -perm /o+w -type f 2>/dev/null # Исполняемые файлы текущего пользователя find ~/bin -perm /u+x -type f
Аудит безопасности: поиск потенциально опасных файлов с избыточными правами.
Советы и предупреждения
Сначала запустите
find . -name "*.tmp" (без -delete) и убедитесь,
что список файлов соответствует ожидаемому. Только после этого добавляйте -delete.
Это правило помогает избежать случайного удаления нужных файлов.
-exec cmd {} + передаёт все найденные файлы одним вызовом команды (как xargs),
а -exec cmd {} \; создаёт отдельный процесс для каждого файла. При тысячах файлов
разница в производительности огромна. Используйте + везде, где команда принимает несколько аргументов.
Имена файлов с пробелами, переносами или спецсимволами ломают стандартный pipe через
xargs.
Безопасный шаблон: find . -name "*.txt" -print0 | xargs -0 grep "pattern" — нулевой
байт-разделитель гарантирует корректную передачу любых имён.
Флаг
-delete автоматически включает -depth, то есть содержимое директории
обрабатывается прежде самой директории. Это необходимо для корректного рекурсивного удаления, но может
изменить порядок вывода, если вы комбинируете -delete с -print.
find / на корневой системе с миллионами файлов может занять минуты и создать
значительную нагрузку на I/O. Всегда ограничивайте область поиска конкретным каталогом
и используйте -maxdepth там, где полная рекурсия не нужна. Альтернатива для частых
поисков — команда locate с предварительно построенной базой данных.