← Весь справочник

find

Поиск файлов по имени, типу, размеру, времени изменения и правам

find обходит дерево каталогов и для каждого файла проверяет условия, которые ты задал. Подходящие файлы печатает или передаёт команде. В отличие от ls и масок оболочки, find спускается во все подкаталоги и умеет выбирать по любым свойствам файла.

Синтаксис

find [-H|-L|-P] [где искать…] [опции обхода] [условия] [действие]

Если путь не указан, ищет в текущем каталоге. Условия читаются слева направо и по умолчанию соединяются через «и». Без действия find просто печатает пути (-print).

Опции обхода

ОпцияЧто делает
-maxdepth Nне спускаться глубже N уровней (0 — только сами стартовые пути, 1 — их содержимое)
-mindepth Nне проверять файлы ближе N уровней (-mindepth 1 исключает сам стартовый каталог)
-xdevне переходить на другие файловые системы (/proc, смонтированные тома)
-depthсначала содержимое каталога, потом сам каталог
-P / -L / -Hссылки не разыменовывать (по умолчанию) / разыменовывать все / только указанные в командной строке
-regextype posix-extendedсинтаксис регулярных выражений для -regex

-maxdepth, -mindepth, -xdev, -depth действуют на всё выражение, где бы ни стояли. Пиши их сразу после пути — так читается однозначно.

Условия: имя и путь

УсловиеЧто значит
-name 'шаблон'имя файла (без каталога) по шаблону оболочки: *, ?, [abc]; -iname — без учёта регистра
-path 'шаблон'весь путь, как его печатает find, например './src/*/test/*'; -ipath — без учёта регистра
-regex 'выражение'регулярное выражение по всему пути; -iregex — без учёта регистра
-lname 'шаблон'символическая ссылка, указывающая на путь по шаблону

Условия: тип файла

УсловиеЧто значит
-type f / d / lобычный файл / каталог / символическая ссылка
-type p / s / b / cименованный канал / сокет / блочное / символьное устройство
-type f,dлюбой из перечисленных типов (GNU)
-xtype lссылка, цель которой не существует («висячая»)
-emptyпустой файл или пустой каталог

Условия: размер и время

УсловиеЧто значит
-size +10M / -size -1kбольше 10 МиБ / меньше 1 КиБ; единицы c (байты), k, M, G; размер округляется вверх до единицы
-mtime +7 / -mtime -1 / -mtime 0изменён больше 7 полных суток назад / меньше суток назад / в последние 24 часа
-mmin +30изменён больше 30 минут назад; -mmin -5 — в последние 5 минут
-atime, -aminто же по времени последнего чтения
-ctime, -cminто же по времени изменения метаданных (права, владелец, переименование)
-newer файлизменён позже, чем указанный файл
-newermt '2024-06-01 12:00'изменён позже указанной даты; ! -newermt … — не позже
-daystartсчитать сутки от начала сегодняшнего дня, а не от текущего момента (ставь перед -mtime)

Условия: владелец, права, ссылки

УсловиеЧто значит
-user имя / -group имявладелец / группа (можно числом)
-uid N / -gid Nчисловой UID / GID
-nouser / -nogroupу файла UID/GID, которого нет в системе
-perm 644права ровно 644
-perm -u+x или -perm -0111стоят все указанные биты (могут быть и другие)
-perm /u+s,g+s или -perm /6000стоит хотя бы один из указанных битов
-readable / -writable / -executableтекущий пользователь может читать / писать / запускать
-links Nчисло жёстких ссылок; -links +1 — у файла есть другие имена
-inum N / -samefile файлпо номеру inode / все имена того же файла

Операторы

ОператорЧто значит
A B или A -a B«и» (-and)
A -o B«или» (-or); у «и» приоритет выше
! A или -not A«не»
\( … \)группировка; скобки экранируй от оболочки и отделяй пробелами

Действия

ДействиеЧто делает
-printпечатает путь (действие по умолчанию)
-print0печатает пути через нулевой байт — пара для xargs -0
-printf 'формат'печатает по шаблону (см. ниже); перевод строки — \n явно
-lsподробная строка, как ls -dils
-fprint файлпишет пути в файл, а не на экран
-deleteудаляет найденное; каталоги — только пустые
-exec команда {} \;запускает команду для каждого файла; {} — путь
-exec команда {} +запускает команду один раз на пачку файлов — быстрее; {} должен стоять последним
-execdir команда {} \;то же, но запускает в каталоге найденного файла
-ok команда {} \;как -exec, но спрашивает подтверждение на каждый файл
-pruneне спускаться в этот каталог
-quitостановиться сразу после первого совпадения

-exec … \; работает и как условие: истинно, если команда вернула 0. Так можно фильтровать любой проверкой: -exec grep -q текст {} \; -print.

Формат -printf и -ls

ДирективаЧто выводит
%p / %Pпуть / путь без стартового каталога
%f / %hимя файла / каталог, в котором он лежит
%s / %kразмер в байтах / занятое место в КиБ
%m / %Mправа числом (644) / буквами (-rw-r--r--)
%u / %gвладелец / группа
%TY-%Tm-%Td %TH:%TMдата изменения по частям; %t — целиком, %T@ — секунды с 1970 года
%y / %d / %nтип (f, d, l) / глубина / число жёстких ссылок
%lкуда указывает символическая ссылка

Строка -ls: номер inode, занятое место в КиБ, права, число ссылок, владелец, группа, размер в байтах, дата изменения, путь.

Примеры

# все .conf в /etc, только обычные файлы
find /etc -type f -name '*.conf'

# файлы больше 100 МиБ на корневой ФС, ошибки доступа — в /dev/null
find / -xdev -type f -size +100M 2>/dev/null

# логи старше 7 суток
find /var/log -name '*.log' -mtime +7

# изменённые за последние 30 минут
find ~/project -type f -mmin -30

# изменённые в заданном промежутке дат
find /srv/app -newermt '2024-01-01' ! -newermt '2024-02-01'

# пустые каталоги в текущем каталоге, без спуска внутрь вложенных
find . -maxdepth 1 -type d -empty

# .log ИЛИ .tmp — группировку скобками экранируй от оболочки
find . \( -name '*.log' -o -name '*.tmp' \) -type f

# не заходить в node_modules и .git
find . \( -name node_modules -o -name .git \) -prune -o -type f -print

# файлы с setuid-битом во всей системе
find / -xdev -type f -perm -4000 2>/dev/null

# файлы, у владельца которых нет учётной записи
find /home -nouser

# размер, права и имя в своём формате, крупные файлы сверху
find /var/log -type f -printf '%s\t%m\t%p\n' | sort -rn | head

# посчитать строки во всех .py одним вызовом wc
find . -name '*.py' -exec wc -l {} +

# оставить только файлы, в которых есть строка
find /etc -name '*.conf' -exec grep -q 'include' {} \; -print

# безопасно передать имена с пробелами в xargs
find . -name '*.bak' -print0 | xargs -0 rm --

# удалить старые временные файлы (сначала проверь без -delete)
find /tmp -type f -name '*.tmp' -mtime +3 -delete

# первое совпадение — и хватит
find / -name 'nginx.conf' -print -quit 2>/dev/null

Подводные камни

  • Шаблон без кавычек раскроет оболочка до запуска find. find . -name *.log при одном .log-файле в текущем каталоге превратится в -name app.log и найдёт только файлы с этим именем, а при нескольких — сломается («paths must precede expression»), если их несколько. Всегда бери шаблон в кавычки.
  • -name смотрит только на имя. -name 'src/*.js' никогда не совпадёт — для пути есть -path. А -regex, наоборот, сравнивается со всем путём: -regex '.*\.log', а не -regex '\.log'.
  • -mtime +7 — это «больше 7 полных суток», то есть фактически 8 и больше: дробная часть отбрасывается. -mtime 7 — от 7 до 8 суток назад.
  • Размер округляется вверх. -size -1M находит только пустые файлы: файл в 1 байт уже считается «1 мегабайтом». Для точных порогов используй c (байты) или k.
  • Порядок важен. -delete в начале выражения удалит всё подряд, до проверки остальных условий. Сначала запусти без -delete и посмотри список.
  • -delete и -prune несовместимы: -delete включает -depth, при котором -prune не работает, и find откажется запускаться. Непустые каталоги -delete не удаляет («Directory not empty»).
  • -o без скобок. find . -name '*.log' -o -name '*.tmp' -print напечатает только .tmp: -print привязан ко второй половине. Бери «или» в \( … \).
  • -exec … {} +: {} должен стоять прямо перед +, иначе «missing argument to `-exec'».
  • Код возврата. «Ничего не найдено» — это успех (код 0). Ненулевой код означает ошибки: нет каталога, нет доступа. Проверяй вывод, а не код.
  • Имена с пробелами и переводами строк ломают find … | xargs. Используй -print0 с xargs -0 или -exec … {} +.

См. также

xargs · ls · stat · chmod · grep · tar · df-du