linux files

find

Поиск файлов и директорий по критериям с возможностью выполнения действий

Описание

find — мощная утилита поиска файлов в файловой системе по множеству критериев: имени, типу, размеру, правам доступа, дате модификации, владельцу и другим атрибутам. Команда обходит дерево каталогов начиная с указанной точки и проверяет каждый файл против набора выражений-фильтров.

Главное отличие find от простого glob-поиска оболочки — возможность поиска по множеству критериев одновременно, рекурсивность, поиск по метаданным (размер, дата, права), а главное — возможность немедленно выполнить действие с найденным файлом через флаг -exec или -delete. Это делает find незаменимым инструментом системного администратора.

Синтаксис find необычен для командной строки Unix — он больше похож на язык запросов с операторами И (-a), ИЛИ (-o) и отрицанием (!). Выражения вычисляются слева направо с поддержкой скобок. Это позволяет строить сложные составные условия поиска.

Синтаксис

find [ПУТЬ...] [ВЫРАЖЕНИЕ]

Структура выражения:

find ПУТЬ [ОПЦИИ] [ТЕСТЫ] [ДЕЙСТВИЯ] # ТЕСТЫ (фильтры): -name, -type, -size, -mtime, -perm, -user, ... # ДЕЙСТВИЯ: -print, -delete, -exec, -ls, -print0 # ОПЕРАТОРЫ: -a (AND, по умолчанию), -o (OR), ! (NOT), \( \) (скобки) # Примеры составных выражений: find . -name "*.py" -a -size +10k # И (оба условия) find . -name "*.bak" -o -name "*.tmp" # ИЛИ (любое условие) find . ! -name "*.py" # НЕ (отрицание)

Флаги и опции

Глобальные опции

Флаг Описание Пример
-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

Аудит безопасности: поиск потенциально опасных файлов с избыточными правами.

Советы и предупреждения

Совет: тестируйте без -delete перед удалением
Сначала запустите find . -name "*.tmp" (без -delete) и убедитесь, что список файлов соответствует ожидаемому. Только после этого добавляйте -delete. Это правило помогает избежать случайного удаления нужных файлов.
Совет: {} + быстрее, чем {} \;
-exec cmd {} + передаёт все найденные файлы одним вызовом команды (как xargs), а -exec cmd {} \; создаёт отдельный процесс для каждого файла. При тысячах файлов разница в производительности огромна. Используйте + везде, где команда принимает несколько аргументов.
Совет: -print0 + xargs -0 для имён с пробелами
Имена файлов с пробелами, переносами или спецсимволами ломают стандартный pipe через xargs. Безопасный шаблон: find . -name "*.txt" -print0 | xargs -0 grep "pattern" — нулевой байт-разделитель гарантирует корректную передачу любых имён.
Внимание: -delete подразумевает -depth
Флаг -delete автоматически включает -depth, то есть содержимое директории обрабатывается прежде самой директории. Это необходимо для корректного рекурсивного удаления, но может изменить порядок вывода, если вы комбинируете -delete с -print.
Внимание: производительность на больших деревьях
find / на корневой системе с миллионами файлов может занять минуты и создать значительную нагрузку на I/O. Всегда ограничивайте область поиска конкретным каталогом и используйте -maxdepth там, где полная рекурсия не нужна. Альтернатива для частых поисков — команда locate с предварительно построенной базой данных.