find в Linux: руководство по поиску файлов с примерами для Ubuntu
find — самый мощный инструмент поиска файлов в Linux. В отличие от locate он смотрит файловую систему вживую, поддерживает фильтрацию по имени, размеру, времени изменения, правам, владельцу и умеет выполнять действие над найденным. Разбираем синтаксис, ключевые предикаты и десяток рецептов, которые покрывают 95% реальных задач администратора Ubuntu.
Зачем нужен find
find — стандартная утилита поиска файлов в Linux. На Ubuntu она уже установлена в составе coreutils, отдельно ставить не нужно. В отличие от locate, который ищет по предварительно построенному индексу mlocate.db, find обходит файловую систему в реальном времени — поэтому видит свежесозданные файлы и работает на любом смонтированном каталоге, включая сетевые шары и временные файловые системы.
Главные сценарии использования:
- Найти файлы по маске имени в большом дереве каталогов.
- Найти всё, что не открывалось дольше 30 дней — для очистки.
- Найти файлы тяжелее 1 ГБ, которые забивают диск.
- Найти файлы с неправильными правами доступа.
- Применить команду к каждому найденному файлу — массовое переименование, удаление, чмоды.
Базовый синтаксис
find [где_искать] [условия] [действие]
[где_искать]— путь, с которого начать обход. Если опущен — текущая директория..[условия](predicates) — фильтры:-name,-type,-size,-mtimeи десятки других.[действие]— что сделать с найденным. По умолчанию —-print(вывести путь в stdout).
Самый простой пример — найти все файлы в текущей директории и её поддиректориях:
find .
Большая часть реальной работы — комбинации условий и одно действие.
Поиск по имени
-name — поиск по точному совпадению имени файла. Поддерживает шаблоны: *, ?, […].
# Все .conf файлы в /etc
sudo find /etc -name "*.conf"
# Конкретный файл по имени
find ~ -name "report.pdf"
# Несколько расширений сразу
find /var/log -name "*.log" -o -name "*.gz"
-iname — то же, но без учёта регистра:
find . -iname "readme*" # найдёт README, ReadMe, readme.md, README.txt
Шаблоны интерпретируются самим find, не shell — поэтому обязательно в кавычках, иначе bash раскроет * до запуска find.
Поиск по типу
-type фильтрует по типу объекта:
| Код | Что значит |
|---|---|
f |
обычный файл |
d |
директория |
l |
симлинк |
b |
блочное устройство |
c |
символьное устройство |
p |
named pipe |
s |
сокет |
# Только директории с именем .git
find / -type d -name ".git" 2>/dev/null
# Все симлинки в /usr/bin
find /usr/bin -type l
# Файлы без типа директории — например, для подсчёта только файлов
find . -type f | wc -l
2>/dev/null гасит ошибки доступа — типичные при обходе системных каталогов без sudo.
Поиск по размеру
-size принимает число с суффиксом:
| Суффикс | Единица |
|---|---|
c |
байт |
k |
килобайт (1024) |
M |
мегабайт |
G |
гигабайт |
| без суффикса | блок 512 байт |
# Файлы тяжелее 1 ГБ
find / -type f -size +1G 2>/dev/null
# Файлы между 10 и 100 МБ
find . -type f -size +10M -size -100M
# Пустые файлы
find . -type f -size 0c
# Маленькие .log файлы
find /var/log -name "*.log" -size -1M
Префиксы: +N больше N, -N меньше N, N точно равно N.
Поиск по времени
Три времени каждого файла:
- mtime — modification time, когда последний раз менялось содержимое.
- atime — access time, когда последний раз читалось.
- ctime — change time, когда последний раз менялись метаданные (права, владелец, имя).
Числа — в днях:
# Файлы, изменённые за последние 7 дней
find /var/log -type f -mtime -7
# Файлы, не открывавшиеся больше 30 дней
find /home -type f -atime +30
# Файлы, у которых изменилось что угодно за последний день
find / -type f -ctime -1 2>/dev/null
Для минут и часов есть -mmin, -amin, -cmin:
# Изменения за последние 5 минут (полезно для отладки)
find /etc -mmin -5
Если нужно сравнение со временем конкретного файла — -newer:
# Файлы, изменённые позже /tmp/marker
find . -newer /tmp/marker
Поиск по правам
-perm принимает права в восьмеричной или символической записи:
# Файлы с правами ровно 0644
find . -type f -perm 0644
# Файлы, у которых разрешена запись для всех (other-write)
find / -type f -perm /o=w 2>/dev/null
# Файлы с SUID-битом
find / -type f -perm /4000 2>/dev/null
# Скрипты, доступные только владельцу (700)
find ~/scripts -type f -perm 0700
Префиксы:
0644— точное совпадение.-0644— все указанные биты должны быть выставлены (может быть больше)./0644— хотя бы один из указанных битов выставлен.
-perm /4000 — классический SecOps-запрос: найти все файлы с SUID-битом, который часто становится вектором эскалации привилегий.
Поиск по владельцу
# Файлы пользователя deploy
find /var -user deploy
# Файлы группы www-data
find /var/www -group www-data
# Файлы без валидного владельца (сирые)
find / -nouser 2>/dev/null
find / -nogroup 2>/dev/null
-nouser / -nogroup — полезны для аудита после удаления учётных записей, чтобы найти зависшие файлы.
Сложные условия
find поддерживает логические операторы:
# И (по умолчанию между условиями)
find . -type f -name "*.log"
# Явное И
find . -type f -a -name "*.log"
# ИЛИ
find . -name "*.log" -o -name "*.gz"
# НЕ
find . -type f -not -name "*.tmp"
# Группировка через экранированные скобки
find . \( -name "*.log" -o -name "*.txt" \) -type f -mtime -7
Без скобок логические операторы могут связываться не так, как ожидается. При сложных запросах — всегда группируйте через \( \).
Действия над найденным
-print, -ls
По умолчанию find печатает путь к найденному. -ls — выводит как ls -l:
find /var/log -name "*.log" -ls
-delete
Удаляет найденное. Опасный режим — без find сначала через -print посмотрите, что попадёт под удаление.
# Сначала проверка
find /tmp -type f -mtime +7
# Потом удаление
find /tmp -type f -mtime +7 -delete
-exec
Выполняет произвольную команду. {} — место подстановки имени найденного файла. Заканчивается на \;.
# Изменить права на все .sh скрипты
find ~/scripts -name "*.sh" -exec chmod +x {} \;
# Скопировать все .conf файлы в бэкап
find /etc -name "*.conf" -exec cp {} /backup/etc/ \;
# Удалить старые логи с подтверждением
find /var/log -name "*.log" -mtime +30 -ok rm {} \;
-ok — то же, что -exec, но запрашивает подтверждение перед каждой командой.
-exec ... +
Альтернативный синтаксис -exec: вместо \; использовать +. Тогда find соберёт несколько найденных файлов в одну команду — быстрее при больших объёмах.
# Медленно: запуск chmod на каждый файл
find . -name "*.sh" -exec chmod +x {} \;
# Быстро: один chmod на пачку файлов
find . -name "*.sh" -exec chmod +x {} +
find + xargs
Альтернатива -exec — конвейер через xargs:
find . -name "*.log" | xargs gzip
Главная гошка xargs: если в именах файлов есть пробелы или спецсимволы — сломается. Решение — флаги -print0 у find и -0 у xargs:
find . -name "*.log" -print0 | xargs -0 gzip
Между -exec ... + и xargs разница в производительности почти не заметна; выбор — вопрос привычки.
Десять рецептов на каждый день
# 1. Топ-10 самых больших файлов в /var
sudo find /var -type f -exec du -h {} + 2>/dev/null | sort -rh | head
# 2. Все .pid файлы (демоны)
sudo find /var/run -name "*.pid"
# 3. Файлы, открытые на запись для всех (мира)
sudo find / -type f -perm -o=w 2>/dev/null
# 4. SUID-программы (аудит безопасности)
sudo find / -type f -perm /4000 2>/dev/null
# 5. Пустые директории
find /opt -type d -empty
# 6. Сжать все .log старше недели
sudo find /var/log -name "*.log" -mtime +7 -exec gzip {} +
# 7. Найти и удалить .DS_Store от macOS
find . -name ".DS_Store" -delete
# 8. Файлы определённого пользователя в /tmp
sudo find /tmp -user nobody
# 9. Симлинки, ведущие в никуда (broken)
find / -type l ! -exec test -e {} \; -print 2>/dev/null
# 10. Сменить владельца на www-data для всех .php
sudo find /var/www -name "*.php" -exec chown www-data:www-data {} +
find vs locate vs which
Три похожих инструмента, разные задачи:
| Утилита | Что ищет | Где | Скорость | Свежесть |
|---|---|---|---|---|
find |
по любому критерию | в реальной ФС | медленно на больших деревьях | актуально |
locate |
по имени | в предварительном индексе mlocate.db |
мгновенно | до последнего updatedb (обычно раз в сутки) |
which |
исполняемые в $PATH |
только в каталогах из PATH | мгновенно | актуально |
whereis |
бинарь + man + исходники | по стандартным путям | мгновенно | актуально |
Используйте find, когда нужны фильтры; locate — для быстрого поиска по имени в стабильной системе; which — чтобы понять, какая версия программы запускается.
locate на Ubuntu 24.04 в стандартной поставке нет — устанавливается отдельно:
sudo apt install plocate
sudo updatedb # пересобрать индекс
locate hosts
Частые вопросы
Чем отличается find от locate?
find обходит файловую систему в реальном времени и поддерживает фильтры по размеру, времени, правам и так далее. locate ищет только по имени, но мгновенно — потому что использует заранее построенный индекс mlocate.db. Если важна актуальность данных или нужны сложные фильтры — find; если нужно быстро найти файл по имени в стабильной системе — locate.
Как использовать find с пробелами в именах файлов?
Если просто find ... | xargs ..., пробелы в именах сломают команду. Решение — использовать null-разделитель: find . -name "*.txt" -print0 | xargs -0 grep "TODO". Альтернатива — find ... -exec ... {} +, который автоматически экранирует имена.
Как найти и удалить файлы старше N дней?
find <путь> -type f -mtime +<N> -delete. Перед удалением обязательно проверьте список без -delete, чтобы не снести нужное. Например, очистка /tmp от файлов старше недели: find /tmp -type f -mtime +7 -delete.
Почему find выводит ошибки «Permission denied»?
Это нормально при обходе системных каталогов без sudo. Глушите их так: find / -name "*.conf" 2>/dev/null. Если нужны и системные файлы — запускайте через sudo find /....
Можно ли использовать регулярные выражения вместо шаблонов?
Да, флаг -regex (соответствует всему пути, не только имени) и -iregex для регистронезависимого варианта. Тип регулярки выбирается опцией -regextype: posix-basic, posix-extended, emacs, posix-egrep. Пример: find . -regextype posix-extended -regex ".*\\.(jpg|png|gif)$".
Что запомнить
find— поиск в реальном времени с любыми фильтрами; не требует индекса.- Базовый синтаксис:
find <путь> <условия> <действие>. - Ключевые предикаты:
-name,-type,-size,-mtime,-perm,-user. - Шаблоны имени всегда в кавычках, иначе bash раскроет
*до find. - Логические операторы:
-a(по умолчанию),-o,-not, группировка через\(\). - Действия:
-print(дефолт),-delete,-exec ... +,-ok(с подтверждением). - Для конвейера через
xargs— обязательно-print0и-0. find— медленный, но точный; для быстрого поиска по имени —plocate.