На этой странице рассказано, как находить файлы, соответствующие заданным Вами критериям, и как выполнять различные действия с найденными файлами.
Основными программами для этих задач являются find
и xargs
.
Некоторые примеры на этой странице используют возможности, характерные для GNU-версий этих программ.
1.1 Область применения
Для краткости, словом файл ниже будем обозначать любой файл в файловой системе:
- обычный файл: текст, картинка, видео и пр.,
- каталог (директория),
- символическую ссылку ,
- любой другой файл, имеющий указание в каком-то каталоге.
Запись в каталоге (директории) также называется именем файла.
Разные примеры того, что ниже называется путём файла:
parser.c
README
./budget/may-94.sc
fred/.cshrc
/usr/local/include/termcap.h
Дерево каталогов - это каталог и содержащиеся в нем файлы, все его подкаталоги и содержащиеся в них файлы и т.д. его подкаталоги и содержащиеся в них файлы и т.д.
Один регулярный файл без каталогов, в целом, тоже можно считать деревом (но маленьким, из одной вершины).
С помощью find
можно найти в одном или нескольких деревьях каталогов файлы, которые:
- имеют имена, содержащие определенный текст или соответствующие определенному шаблону;
- являются ссылками на определенные файлы;
- использовались в последний раз в течение определенного периода времени;
- находятся в определенном диапазоне размеров;
- имеют определенный тип (обычный файл, каталог, символическая ссылка и т.д.);
- принадлежат определенному пользователю или группе;
- имеют определенные разрешения доступа или биты специального режима;
- содержат текст, соответствующий определенному шаблону;
- находятся на определенной глубине в дереве каталогов;
- или некоторые комбинации вышеперечисленного.
Найденные файлы можно обработать различными способами, как по отдельности, так и в группах разного размера.
Действия, которые можно совершить с найденными файлами, включают следующий список (хотя и не ограничиваются на нём):
- просмотр или редактирование
- сохранить в архиве
- удалить или переименовать
- изменить права доступа
- классифицировать по группам
1.2 Быстрый старт
Обзор
find [ФАЙЛ...] [ВЫРАЖЕНИЕ]
Команда
find
ищет файлы в дереве каталоговФАЙЛ
, для каждого файла вычисляетВЫРАЖЕНИЕ
и, если оно истинно, то (по умолчанию) выводит имя файла.В выражении
ВЫРАЖЕНИЕ
обычно указаны какие-то критерии поиска.
Поиск файлов в
/usr/src
с расширением.c
, размером более 100 Кб:find /usr/src -name '*.c' -size +100k -print
Обратите внимание, что паттерн
*.c
заключён в кавычки ('*.c'
), чтобы shell не интерпретировал его и передал вfind
без изменений.Вывод имени — не единственное, что можно делать с найденными файлами, см. Выполнение команд
2 Выражения
2.1 Выражения ‘find’
Выражение состоит из одного или нескольких “атомов”.
Атомы — это аргументы и флаги командной строки; иногда один атом может состоять из
нескольких аргументов: например, когда у флага есть аргумент: -printf '%f'
.
Атомы можно разбить на четыре категории:
Параметр
влияет на общую работу, а не на обработку отдельного файла;
Действует сразу, не вычисляется для каждого файла по мере его обработки.
Исключения:
-daystart
и-follow
, влияющие по-разному в зависимости от места в командной строке. Рекомендуется размещать их в начале.
Тест
возвращает true или false, основываясь на атрибутах файла;
Действие
вызывает побочные эффекты и возвращает истину или ложь;
Композиция
атомы, которые как-то объединяют другие атомы, влияя на порядок их вычисления и определяя вычислятся ли они вообще.
Можно опустить оператор между двумя аргументами; по умолчанию используется
-and
. См. 2.12 Комбинирование аргументов с операторами
Действие -print
выполняется для всех файлов, для которых ВЫРАЖЕНИЕ
истинно (*см. Печать имени файла::).
~Исключение: это правило может не работать, если есть флаги -prune
или -quit
.
Действия, отключающие -print
по умолчанию: -delete
, -exec
, -execdir
, -ok
, -okdir
, -fls
, -fprint
, -fprintf
, -ls
, -print
, -printf
.
Многие флаги требуют аргументов, следующих за ними в командной строке find
.
Аргументы могут быть именами файлов, шаблонами, строками или числами.
Числовые аргументы могут быть указаны как:
Аргумент:
+N
для чисел больше N,
Аргумент:
-N
для чисел меньше N,
Аргумент:
N
2.2 Начальные точки
GNU find
начинает поиск в указанных каталогах, применяя заданное выражение к каждому найденному файлу.
Процесс продолжается до тех пор, пока не будет определён результат выражения - ложь для “and” или истина для “or”.
После этого find
переходит к следующему файлу.
2.3 Поиск по имени файла
GNU find
предлагает гибкие возможности для поиска файлов по именам, как с точным соответствием шаблону, так и с более общим.
2.3.1 Поиск по имени
Поиск по имени файла, не учитывая путь файлу.
Тест
-name шаблон
Проверяет, соответствует ли имя файла шаблону
шаблон
. Учитывает регистр.
Тест
-iname шаблон
То же, что и
-name
, но без учёта регистра.
2.3.2 Поиск по полному пути
Тест
-path шаблон
-wholename шаблон
Сравнивает весь путь файла с шаблоном
шаблон
.
Тест
-ipath шаблон
-iwholename шаблон
Версии
-path
и-wholename
, не учитывающие регистр.
2.3.3 Шаблоны
В find
используются специальные символы и подстановочные знаки для сопоставления шаблонов имен.
Специальные символы:
*
соответствует любому количеству символов.?
соответствует одному символу.[STRING]
соответствует одному символу из строкиSTRING
, которая может включать диапазоны.\
убирает специальное значение следующего за ним символа.
Для детальной информации об этих опциях см. info findutils
.
Шаблон shell - это строка, содержащая специальные символы, известные как глобы.
Шаблоны с глобами следует заключать в кавычки, чтобы оболочка не интерпретировала их самостоятельно.
Используйте одинарные, двойные кавычки или экранирование с помощью обратной косой черты для предотвращения раскрытия оболочкой.
2.4 Ссылки
Файлы могут быть связаны двумя способами: символическими и жесткими ссылками.
2.4.1 Символические ссылки
Символические ссылки - это файлы, содержащие путь к другому файлу.
Обработка символических ссылок в
find
:
- Разыменование ссылок:
find
проверяет файл, на который указывает ссылка.- Проверка самой ссылки:
find
может анализировать саму ссылку без разыменования.По умолчанию
find
проверяет ссылки при их обнаружении и файлы, на которые они указывают, при последующих встречах.
- Используйте
-L
для исключения ссылок и анализа связанных файлов.-P
устанавливает поведение по умолчанию.-H
частично разграничивает символические ссылки, указанные в командной строке.
Тест
-lname шаблон
Истина, если символическая ссылка соответствует шаблону
шаблон
.-ilname
игнорирует регистр.
2.4.2 Жесткие ссылки
Жесткие ссылки - это разные имена файла, ссылающиеся на один и тот же инод.
Тест
-samefile ИМЯ
Истина, если файл является жесткой ссылкой на тот же инод, что и ИМЯ.
Тесты для анализа количества жестких ссылок:
-inum n -links n -links +n -links -n
Проверяют номер инода и количество жестких ссылок.
2.5 Время
Каждый файл имеет три временные метки: доступ, изменение и модификация. Некоторые системы также предоставляют метку создания файла.
2.5.1 Диапазоны времени
find
позволяет искать файлы по временным меткам в определенных диапазонах.
Тесты времени:
-atime n -ctime n -mtime n -amin n -cmin n -mmin n -daystart
Проверяют время доступа, изменения и модификации файла.
2.5.2 Сравнение временных меток
Тесты для сравнения временных меток:
-newerXY ссылка -anewer ссылка -cnewer ссылка -newer ссылка -used n
Сравнивают временные метки текущего файла с файлом-ссылкой.
Для более подробной информации о работе с временными метками и ссылками в find
обратитесь к info findutils
.
2.6 Размер
Тест
-size n[bckwMG]
Истина, если файл занимает N единиц пространства с округлением в большую сторону. Единицы могут быть указаны с помощью суффиксов типа
b
,c
,w
,k
,M
,G
.
Тест
-empty
Истина, если файл пуст и является либо обычным файлом, либо каталогом.
2.7 Type
Тест
-type c
Истина, если файл имеет тип C (‘b’, ‘c’, ‘d’, ‘p’, ‘f’, ‘l’, ‘s’, ‘D’).
Тест
-xtype c
Ведет себя так же, как и
-type
, если только файл не является символической ссылкой. Проверяет тип файла, который не проверяет-type
.
2.8 Владелец файла
find
позволяет искать файлы на основе информации о владельце и группе.
Тесты для определения владельца файла:
-user имя_пользователя -group имя_группы -uid n -gid n
Проверяют, принадлежит ли файл определенному пользователю или группе, используя имена или числовые идентификаторы.
Тесты для поиска файлов без владельца или группы:
-nouser -nogroup
Истина, если файл не имеет владельца или группы, соответствующих существующим пользователям или группам.
2.9 Биты прав на файл
find
также позволяет искать файлы на основе разрешений на них.
Тесты для проверки разрешений файла:
-readable -writable -executable
Проверяют, может ли вызывающий пользователь читать, писать или выполнять файл.
Тест
-perm режим
Истина, если биты режима файла соответствуют указанному
режиму
, который может быть как символьным, так и числовым.
2.10 Поиск по содержимому файла
Для поиска файлов по содержимому используйте комбинацию grep
, find
и xargs
. Например, чтобы найти исходные файлы C в текущем каталоге, содержащие строку ‘thing’:
grep -l thing *.[ch]
Для поиска в подкаталогах:
find . -name '*.[ch]' | xargs grep -l thing
Опция -l
в grep
выводит только имена файлов, содержащих строку. Строка ‘thing’ является регулярным выражением и может содержать метасимволы.
Для улучшения метода используйте -print0
в find
и -0
в xargs
для корректной обработки имен файлов с пробелами:
find . -name '*.[ch]' -print0 | xargs -r -0 grep -l thing
Для детального описания поиска файлов по содержимому см. руководство grep
.
2.11 Обработка каталогов
Управление поиском в каталогах с find
:
Параметр
-maxdepth уровни
Ограничивает поиск до указанного количества уровней каталогов ниже аргументов командной строки.
-maxdepth 0
применяет тесты и действия только к аргументам командной строки.Примеры:
mkdir -p dir/d1/d2/d3/d4/d5/d6 find dir -maxdepth 1
Вывод:
dir dir/d1
find dir -mindepth 5
Вывод:
dir/d1/d2/d3/d4/d5 dir/d1/d2/d3/d4/d5/d6
find dir -mindepth 2 -maxdepth 4
Вывод:
dir/d1/d2 dir/d1/d2/d3 dir/d1/d2/d3/d4
Параметр
-mindepth уровни
Параметр
-depth
Параметр
-d
Действие:
-prune
Не спускаться в каталоги. Применяется только к содержимому обрезанных каталогов.
Пример:
find . -wholename './src/emacs' -prune -o -print
Действие
-quit
Немедленный выход из
find
. Отличается от-prune
тем, что-quit
заставляетfind
остановиться сразу.Пример:
find / -name needle -print -quit
2.12 Операторы для композиции команд
Операторы позволяют составные выражения из тестов и действий.
Операторы располагаются в порядке убывания старшинства:
Композиция
( EXPR )
Принудительный приоритет. Истинно, если EXPR истинен.
Композиция
! EXPR
-not EXPR
Истинно, если EXPR ложно. В некоторых оболочках необходимо защитить ’!’ от интерпретации оболочкой, заключив его в кавычки.
Композиция
EXPR1 EXPR2
EXPR1 -a EXPR2
EXPR1 -and EXPR2
И; EXPR2 не вычисляется, если EXPR1 ложен.
Композиция
EXPR1 -o EXPR2
EXPR1 -or EXPR2
Или; EXPR2 не вычисляется, если EXPR1 истинен.
Композиция
EXPR1 , EXPR2
Список; всегда вычисляются оба EXPR1 и EXPR2.
Истинно, если EXPR2 истинно. Значение EXPR1 отбрасывается.
Этот оператор позволяет Вам выполнять несколько независимых операций в одном обходе, не завися от того, были ли успешны другие операции.
Две операции EXPR1 и EXPR2 не всегда полностью независимы, поскольку EXPR1 может иметь побочные эффекты, такие как касание или удаление файлов, или может использовать
-prune
, что также повлияет на EXPR2.
find
ищет в дереве каталогов, уходящем корнями в каждое имя файла, выполняя выражение слева направо, в соответствии с правилами старшинства, пока результат не будет известен (левая сторона ложна для ‘-and’, истинна для ‘-or’), и тогда find
переходит к следующему имени файла.
Есть еще два теста, которые могут быть полезны в сложных выражениях:
Тест
-true
Всегда верно.
Тест
-false
Всегда ложно.
3 Действия
find
предлагает различные способы вывода информации о файлах, соответствующих заданным критериям.
Можно выводить информацию на стандартный вывод или в файл, а также выполнять команды с именами файлов в качестве аргументов.
3.1 Печать имени файла
Действие:
Выводит полное имя файла на стандартный вывод. Используйте
-print0
для обработки файлов с новыми строками в их именах.
Действие
-fprint файл
Выводит полное имя файла в указанный файл. Если файл не существует, он будет создан.
3.2 Печать информации о файле
Действие
-ls
Выводит информацию о файле в сокращенном формате, аналогичном
ls -dils
.
Действие
-fls файл
Аналогично
-ls
, но записывает информацию в указанный файл.
Действие
-printf формат
Выводит информацию о файле в заданном формате, интерпретируя эскейпы и директивы. Не добавляет новую строку автоматически.
Примеры использования -printf
для настройки формата вывода:
-
Вывод имени файла, его размера и даты последнего изменения:
find /path/to/search -printf "%f\t%s bytes\t%T+\n"
-
Вывод имени файла, владельца и группы:
find /path/to/search -printf "File: %f\tOwner: %u\tGroup: %g\n"
-
Вывод имени файла и его типа:
find /path/to/search -printf "File: %f\tType: %y\n"
Действие
-fprintf файл формат
Аналогично
-printf
, но записывает в указанный файл.
3.3 Выполнеие команд
Вы можете использовать список имен файлов, созданный командой ‘find’, в качестве аргументов к другим командам.
Таким образом, Вы можете выполнять произвольные действия над файлами.
3.3.1 Одиночный файл
Вот как выполнить команду для одного файла за раз.
Действие
-execdir command ;
Выполнение КОМАНДЫ; true, если КОМАНДА возвращает ноль.
find
воспринимает все аргументы после-execdir
как часть команды, пока не будет достигнут аргумент, состоящий из;
. Она заменяет строку{}
на текущее имя файла, обрабатываемое везде, где оно встречается в команде. Обе эти конструкции должны быть экранированы (с помощью\
) или заключены в кавычки, чтобы защитить их от расширения оболочкой. Команда выполняется в директории, которуюfind
искал в момент выполнения действия (то есть, {} расширится до файла в локальной директории).Например, чтобы сравнить каждый заголовочный файл C в текущем каталоге или под ним с файлом
/tmp/master
:find . -name '*.h' -execdir diff -u '{}' /tmp/master ';'
Предупреждение!
Если Вы используете
-execdir
, Вы должны убедиться, что переменнаяPATH
содержит только абсолютные пути каталогов.Наличие пустого элемента в
PATH
или явное включение.
(или любого другого неабсолютного имени) небезопасно.GNU find откажется запускаться, если Вы используете
-execdir
и он считает, что Ваша настройкаPATH
небезопасна.
3.3.2 Обработка нескольких файлов
Основные принципы
Обычно более эффективно обрабатывать несколько файлов за один вызов команды, вместо того чтобы запускать новую команду для каждого файла.
Это экономит время, необходимое для запуска команды каждый раз.
С помощью -execdir
и -exec
можно исполнять команды, содержащие множество файлов
в качестве аргументов.
Использование -execdir
и -exec
Действие
-execdir command {} +
Это действие работает аналогично
-execdir command ;
, но{}
в конце команды раскрывается до списка подходящих файлов. Раскрытие выполняется таким образом, чтобы не превысить максимальную длину командной строки. В команде допускается только один{}
, и он должен находиться в конце, непосредственно перед+
.
Действие
-exec command {} +
Этот вариант, определенный POSIX, работает похожим образом, но выполняет команду в каталоге, из которого был вызван
find
.{}
расширяется до относительного пути, начинающегося с имени одного из начальных каталогов.
Обработка ошибок и выход из find
Перед выходом из find
выполняются все частично построенные командные строки. Это происходит даже если выход был вызван действием -quit
. Однако некоторые типы ошибок могут привести к немедленному фатальному выходу, в таком случае командные строки не будут вызваны.
Решение проблем с расположением аргументов
Иногда требуется, чтобы имена файлов находились не в конце командной строки. Решение этой проблемы заключается в использовании команды sh -c
:
find startpoint -tests ... -exec sh -c 'scp "$@" remote:/dest' {} +
В этом примере "$@"
в команде scp
раскрывается до списка имен файлов.
3.3.2.1 Небезопасная обработка имен файлов
Использование xargs
по умолчанию может быть небезопасным из-за специальных символов в именах файлов. Например, команда из cron
может быть использована для удаления любого файла:
find / -name '#*' -atime +7 -print | xargs rm
Это может привести к удалению критических системных файлов.
3.3.2.2 Безопасная работа с именами файлов
Для безопасной работы с именами файлов используйте опции -0
или --null
с xargs
, tar
, cpio
или perl
.
Например:
find / -name xyzzy -print0 > list
xargs -0 -a list munge
или
find / -name xyzzy -print0 | xargs -0 munge
3.3.2.3 Необычные символы в именах файлов
Обработка необычных символов в именах файлов требует внимания. Например, -print0
и -fprint0
всегда печатают точное имя файла без изменений, даже при выводе в терминал. В то время как -ok
и -okdir
в настоящее время выводят точное имя файла без изменений, это поведение может измениться в будущих выпусках.
Ссылки по теме
- https://cwe.mitre.org/data/definitions/78.html - Описывает инъекцию команд ОС.
- https://cwe.mitre.org/data/definitions/73.html - Описывает проблемы, возникающие при разрешении удаленным компьютерам отправлять запросы, указывающие имена файлов по их выбору.
- https://cwe.mitre.org/data/definitions/116.html - Описывает проблемы, связанные с кодированием имен файлов и экранированием символов.
- https://xkcd.com/327/ - Юмористическое и краткое изложение более широкой проблемы.
3.3.3 Команды с подтверждением пользователем
Для команд, требующих подтверждения пользователя перед выполнением, find
предлагает опции -okdir
и -ok
.
Действие с подтверждением пользователя
-okdir команда
Аналогично
-execdir
, но сначала запрашивает подтверждение пользователя. Если пользователь отказывается, возвращается false.-ok command ;
Менее безопасный вариант, предусмотренный POSIX. Он выполняет команду в директории, из которой была вызвана
find
.