Описание: Утилита find(1) незаменима при поиске файлов с заданными параметрами. Кандидат BSDA должен свободно владеть ею. На экзамене его могут попросить найти файл с заданным последним временем изменения, размером, типом, файловыми флагами, UID, GID, пермиссиями или содержащим в названии какой-то шаблон.
Практика: find(1)
Команда find(1) предназначена для поиска файлов по заданному критерию. Формат команды:
find [опции] где_искать [что искать (условия)] [действие]
Опции могут быть различные, они регулируют поведение
find(1) при поиске. К тому же они в разных
версиях и в разных системах разные. Так, напрмер, опция
-E
, изменяющая синтаксис регулярных выражений в
опциях -regex
и -iregex
подобно аналогичной опции в grep(1), имеется
только в FreeBSD.
Пожалуй важно знать опцию -x
. Она предотвращает
поиск на устройствах отличных от устройства, с которого поиск
начался. Например:
find -x /home/user
Эта команда выведет список всех файлов в домашнем каталоге
пользователя user и во всех подкаталогах, кроме каталогов
являющихся точками монтирования других устройств
(/home/user/mnt/floppy
,
/home/user/mnt/cdrom
,
/home/user/mnt/nfs
).
Путь надо указывать обязательно. Некоторые версии
GNU find проводят поиск
относительно текущего каталога, если им не указать путь,
find в BSD требует явного указания пути. В
особых случаях, когда путь, в котором надо производить поик
имеет необычное имя, можно указать его как аргумент опции
-f
.
Условия для поиска задаются опциями, перечисленными ниже. При
задании нескольких опций, они объединяются через оператор
«и». Связку «и» можно задать явно используя
опцию -and
. Связка «или» задаётся
опцией -or
. Унарное отрицание —
!
и символы группировки —
(...)
, в sh и
csh необходимо защищать используя либо
кавычки, либо \.
-amin n
-cmin n
-mmin n
n
минут. Здесь под временем файла имеется ввиду:
-amin
— access time (время
последнего доступа к файлу),
-cmin
— change of file status
information (время изменения информации о состоянии файла)
-mtime
— modification time
(время изменения файла)
-anewer file
-cnewer file
-mnewer file
-anewer
— access time (время
последнего доступа к файлу),
-cnewer
— change of file
status information (время изменения информации о состоянии
файла) -mnewer
— modification
time (время изменения файла)
-atime n
-ctime n
-mtime n
Условие истинно, если разница между временем когда был
запущен поиск и временем файла округлённая вверх, в
точности n
суток. Здесь под временем
файла имеется ввиду: -amin
—
access time (время последнего доступа к файлу),
-cmin
— change of file status
information (время изменения информации о состоянии файла)
-mtime
— modification time
(время изменения файла)
У времени можно задавать знак:
-mtime -7
— ищем файлы
изменённые за последнюю неделю,
-mtime +7
— ищем файлы
не менявшиеся в течение недели.
В FreeBSD имеется расширение
синтаксиса: опциям -atime
,
-ctime
и -mtime
можно
указывать время с размерностью в секундах, минутах, часах,
днях и неделях. Например 2s
,
3m
, 4h
,
5d
, 6w
. Можно
комбинировать размерности:
5d6w
— шесть недель и пять
дней.
В OpenBSD и NetBSD
для аналогичного поиска придётся пользоваться опциями
-amin
, -cmin
и
-mmin
, переводить время в минуты и
использовать где надо отрицание !
.
-newer file
-newerXY file
Опция есть только в FreeBSD!
Условие истинно, если найденный файл имеет большее время
доступа (X=a
), изменения статуса
(X=c
), модификации (X=m
)
указанного чем время доступа (Y=a
),
изменения статуса (Y=c
), модификации
(Y=m
) у указанного файла.
-empty
-flags [-] flags
-
не указан, условие истинно, если флаги
в точности соответствуют указанным. Если знак
-
указан, условие совпадает, если как
минимум указанные флаги присутствуют.
-perm [-] mode
-
имеет то же
значение, что и в опции -flags
.
-group group
, -user user
-nogroup
, -nouser
-type type
Условие истинно, если найденный файл имеет указанный тип. Возможные типы файла:
b | block special | блочное устройство |
c | character special | символьное устройство |
d | directory | каталог |
f | regular file | обычный файл |
l | symbolic link | символьная ссылка |
p | FIFO | именованный канал |
s | soket | сокет |
-fstype type
local
и
rdonly
.
-[i]name pattern
*
,
?
и []
. Опция
-iname
отличается тем, что игнорирует
регистр.
-[i]path pattern
*
,
?
и []
.
/
считается обычным символом. Вариант
нечувствителоьный к регистру реализован в
FreeBSD и NetBSD.
-[i]regex pattern
Опция не реализована в OpenBSD!
Условие истинно, если имя файла (вместе с путём) полностью
соответствует регулярному выражению
pattern
. Что значит полностью? Шаблон
foo
не соответствует пути
./foo/bar
, а .*foo.*
соответствует. Вариант
-iregex
нечувтвителен к регистру.
-size n[c]
n
блоков по 512 байт. Внимание! команда
find(1) не использует переменную
окружения BLOCKSIZE
. Если указан
суффикс c
, то размер берётся точно в
байтах. Так же как и в случае с опцией
-atime
можно задавать знак:
-size -1024c
— искать
файлы размером меньше килобайта.
-maxdepth n
и -mindepth n
-maxdepth 1
искать файлы только в текущем каталоге, не погружаясь в
подкаталоги.
Простейшее действие — напечатать имя файла на
STDOUT
. Это действие по умолчанию
предпринимается если ничего другого не указано. Оно эквивалентно
указанию опции -print
.
-print
-print0
-ls
-dgils
.
-delete
Опция есть только в FreeBSD!
Удалить найденные файлы и директории.
-exec команда [опции [{}]] ;
{}
, то она будет заменена именем файла (с
путём). Символ ;
означает, что в этом
месте закончилась команда и её опции.
-execdir команда [опции [{}]] ;
-exec
, но при выполнении
команды find(1) переходит в каталог,
где находится файл, а {}
заменяет на имя
файла без пути.
-ok команда [опции [{}]] ;
-exec
, но перед выполнением
команды find(1) запрашивает
подтверждение у пользователя.
-exec команда [опции [{}]] +
Опция есть только в FreeBSD!
Эквивалентна опции -exec ... ;
, но
замещает {}
не одним найденным файлом, а
списком файлов. Таким образом, указанная команда
вызывается лишь однажды. Это работает как же, как связка с
командой xargs(1).
xargs [опции] команда с аргументами
Команда xargs(1) читает список файлов из своего
STDIN
и подставляет эти файлы в качестве
аргумента команде указываемой ей в аргументе. Её удобно
применять в связке с find(1). Например, пусть
нам надо узнать сколько строк в каком из журнальных файлов на
нашей системе.
$
find /var/log \! -name *bz2 -type f | xargs wc -l
875 /var/log/auth.log
125 /var/log/cron
270 /var/log/debug.log
.....
Знак \
перед !
мы поставили для того, чтобы sh не
интерпретировал его по-своему. Аналогичного результата мы могли
бы добиться используя опцию -exec
.
$
find /var/log \! -name *bz2 -type f -exec wc -l {} \;
875 /var/log/auth.log
125 /var/log/cron
270 /var/log/debug.log
.....
Даже на современной, быстродействующей машине разница в выполнении этих двух команд видна невооружённым взглядом. Мы можем её измерить:
$
time find /var/log \! -name *bz2 -type f | xargs wc -l > /dev/null real 0m0.032s user 0m0.000s sys 0m0.024s$
time find /var/log \! -name *bz2 -type f -exec wc -l {} \; > /dev/null real 0m0.242s user 0m0.040s sys 0m0.191s
Разница составила целый порядок. А ведь здесь ещё мало файлов. В
чём же дело? А дело в том, что find(1) с
опцией -exec
для каждого найденного файла
заново вызывает команду wc(1). Вызов команд в
UNIX (и не только в нём) — очень
дорогая процедура. В случае с использованием
xargs(1), мы вызвали wc(1)
только один раз. Подсчёт статистики связанный с чтением и
анализом содержиного файла более прост, чем сам вызов
wc(1).
Ещё очень полезной особенностью xargs(1),
является то, что он может разбирать список файлов с
STDIN
, считая символом разделителем не
пробел, а нулевой символ, которого в принципе не может быть в
имени файла. Это может быть очень важно, например, при работе с
разделами Windows или Macintosh.
$
find /mnt/samba ... -print0 | xargs -0 ...
Теперь, какие бы причудливые имена ни встретились нам, даже если они содержат кавычки, пробелы, символы конца строки, они будут обработаны корректно.