find и xargs: поиск и пакетная обработка

Находим файлы по любым критериям и обрабатываем их пачкой.

find — это команда рекурсивного поиска файлов по имени, типу, размеру, дате и другим признакам, с возможностью сразу выполнить над ними действие.

Поиск по имени и типу

find обходит дерево папок от указанной точки и фильтрует по условиям.

find . -name "*.log"
find /var -type f -name "*.conf"
find . -type d -name "node_modules"

Первая команда ищет все .log от текущей папки, вторая — обычные файлы (-type f) с расширением .conf, третья — папки (-type d) с именем node_modules. Шаблон в -name берите в кавычки, чтобы его раскрыл find, а не Bash.

Фильтры по размеру и времени

УсловиеЗначение
-size +100Mбольше 100 мегабайт
-mtime +7изменён более 7 дней назад
-mtime -1изменён за последние сутки
-emptyпустые файлы или папки
find /var/log -name "*.log" -mtime +30 -size +10M

Эта команда находит старые (больше 30 дней) и крупные (больше 10 МБ) логи — кандидаты на удаление.

Действие над найденным

Опция -exec запускает команду для каждого файла. Символ {} подставляет имя файла, \; завершает команду.

find . -name "*.tmp" -exec rm {} \;
find /var/log -name "*.log" -mtime +30 -delete

Первая удаляет все .tmp, вторая использует встроенный -delete. Будьте осторожны — сначала запустите без удаления, чтобы увидеть список.

xargs: собрать аргументы в одну команду

Запускать -exec для каждого файла отдельно медленно. xargs собирает имена и передаёт их одной команде пачкой:

find . -name "*.log" -print0 | xargs -0 gzip

Связка -print0 и -0 разделяет имена нулевым байтом, а не переводом строки, — это безопасно для файлов с пробелами в имени.

Как работает под капотом

find обходит дерево каталогов вглубь, проверяя каждое условие как фильтр: условия идут слева направо и соединяются логическим И. Когда все условия истинны, выполняется действие (-print по умолчанию). xargs читает поток имён со stdin и строит из них командную строку, не превышая лимит длины аргументов ОС, — поэтому он эффективнее -exec ... \;, который порождает по процессу на файл.

Частые ошибки

  • Шаблон без кавычек. find . -name *.log сначала раскроет Bash; нужно -name "*.log".
  • Пробелы в именах + xargs. Без -print0/-0 имена с пробелами разобьются. Всегда используйте нулевой разделитель.
  • -delete без предпросмотра. Сначала запустите find без действия и убедитесь, что список верный.

Итог

  • find ПУТЬ -type f -name "шаблон" — рекурсивный поиск; фильтры по размеру (-size), времени (-mtime) комбинируются по И.
  • -exec команда {} \; или -delete выполняют действие над найденным.
  • find ... -print0 | xargs -0 команда — быстрая и безопасная пакетная обработка.
Проверьте себя
1. Как найти только обычные файлы (не папки) по имени *.conf?
Afind . -name "*.conf"
Bfind . -type f -name "*.conf"
Cfind . -type d -name "*.conf"
Dfind . -file "*.conf"
2. Зачем в связке find ... | xargs использовать -print0 и -0?
AДля скорости компиляции
BЧтобы корректно обрабатывать имена файлов с пробелами через нулевой разделитель
CЧтобы вывести нули
DЭто обязательно всегда
3. Что подставляет {} в конструкции find ... -exec rm {} \;?
AПустую строку
BИмя текущего найденного файла
CНомер файла
DТекущую папку