Практические примеры, которые приведены в этой статье, помогут вам освоить очень эффективную и крайне полезную команду find.
Она используется для поиска файлов и папок через командную строку Linux.
Команда find — одна из самых мощных и широко применимых команд. При этом она крайне объёмная и насчитывает более 50 опций, в которых легко запутаться, особенно в сочетании с командами exec или xargs.
Если вы сисадмин или разработчик, избежать команды
find при работе с командной строкой не получится. Так что давайте научимся её не бояться и пользоваться её возможностями в полной мере.
Для этого разберём самые распространённые случаи практического применения команды find. Но для начала покажу вам синтаксис и принцип работы с командой.
Команда find в Linux
Общий синтаксис команды find выглядит так:
find [directory to search] [options] [expression]
Всё, что в квадратных скобках, указывать необязательно. А значит, выполнить команду find можно вообще без опций и параметров. Она выдаст список всех файлов и папок в текущем расположении. Мало полезного, да?
Так что давайте взглянем на параметры подробнее:
directory to search (папка поиска) — это расположение, с которого вы хотите начать поиск. Поиск по умолчанию рекурсивный и начинается с текущего расположения.
options (опции) содержит указание типа поиска: по имени, типу файла, времени изменения и так далее — тут может быть более 50 вариантов.
expression (выражение) содержит поисковый запрос. Если вы ищете файл по имени, параметр expression должен содержать имя файла. Если ищете файлы с именем, соответствующим заданному шаблону, поисковое выражение — это шаблон.
Приведу простой пример:
find . -type f -name myfile
Такая команда выполнит поиск файла (именно файла, не папки) с именем
myfile в текущей папке и подпапках. Опция
-type f сужает поиск до файлов. Точка (
.) указывает на текущую папку.
Рассмотрим несколько примеров применения команды find.
Поиск файлов и папок по имени
Так выполняется поиск файлов и папок по имени:
find . -name SEARCH_NAME
Поскольку тип объекта не указан, команда выполняет поиск и файлов, и папок.
Пример ниже — поиск файлов и папок с именем «mystuff»:
Оболочка распознает подстановочный знак * и заменит его всеми файлами в текущей папке, чьи имена заканчиваются на .cpp.
Это сработает, если такой файл всего один, но если их несколько, оболочка пожалуется на некорректный синтаксис.
В нашем случае файл .cpp всего один, и после подстановки команда выглядит так:
find . -type f -name file.cpp. Она работает, поскольку
file.cpp — корректный поисковый запрос.
А вот файлов .txt в той же папке два, и когда команда расширяется до
find . -type f -name another.txt new.txt, выводится предупреждение, потому что поисковых запросов больше одного.
Именно поэтому сам поисковый запрос всегда следует заключать в двойные кавычки.
Поиск нескольких файлов с несколькими расширениями (или условием)
Команда, рассмотренная выше, нужна для поиска файлов по расширению. А что если нужно найти файлы с несколькими разными расширениями?
Вместо того чтобы прогонять команду find несколько раз, введите её один раз с опцией -o, которая работает как логическое условие «или»:
Если нужные вам файлы могут находиться в нескольких папках, можно выполнить поиск во всех этих расположениях за один раз. Просто укажите все пути к папкам при введении команды find:
find ./location1 /second/location -type f -name "pattern"
Поиск пустых файлов и папок
Опция
-empty позволяет использовать команду find для поиска пустых файлов и папок.
Найти таковые в текущей папке можно следующим образом:
find . -empty
Можно указать тип объектов, чтобы искать только файлы или только папки:
find . -empty -type f
Кроме того, можно в таком режиме искать файлы по имени:
find . -empty -type f -name "*.cpp"
Поиск крупных и мелких файлов (поиск по размеру файла)
Команда find поможет найти крупные или мелкие файлы, если выполнить поиск по размеру. Но это работает только для файлов, не для папок.
Используется опция
-size с аргументом +N для файлов размером более N и -N для файлов размером менее N.
А вот как можно найти файлы точного заданного размера (50 КБ):
find . -size 50k
Так выполняется поиск файлов размером более 1 ГБ в текущей папке:
find . -size +1G
А так — файлов, не превышающих 20 байт:
find . -size -20c
Для поиска файлов размером более 100 МБ, но менее 2ГБ, введите:
find . -size +100M -size -2G
Поиск по размеру тоже можно сочетать с поиском по имени файла. Таким образом, найти в корневом каталоге все файлы размером более 500 МБ с именем, оканчивающимся на .log, можно так:
find / -size +500M -name "*.log"
Для справки:
c – байты
k – килобайты
M – мегабайты
G – гигабайты
Поиск недавно изменённых файлов (поиск по времени изменения или создания)
Вы не раз столкнётесь с ситуацией, когда нужен список всех недавно изменённых файлов. В таких случаях на помощь приходит поиск по времени изменения.
Найти все файлы, претерпевшие изменения за последние трое суток (3*24ч), можно так:
find . -type f -mtime -3
А все файлы, созданные пять и более дней назад, ищутся так:
find . -type f -ctime +5
Понимаю, что 24 часа — большой срок. Что если нужно выявить файлы, изменённые всего пару минут назад? Для этого предусмотрены опции
mmin,
amin и
cmin.
Так выглядит команда поиска всех файлов, изменённых за последние пять минут:
find . -type f -mmin -5
Можно не только указать имя файла, но и ограничить временной промежуток с двух сторон. Команда ниже выполнит поиск всех файлов .java, изменённых не ранее 30 и не позднее 20 минут назад.
Команда find позволяет выполнить поиск файлов по разрешению и режиму доступа.
find -perm mode
Поищем в текущей папке, к примеру, все файлы с режимом доступа 777:
find . -perm 777
А так можно найти все файлы с правами на чтение и запись для всех типов пользователей (только точное совпадение; файлы с правами на выполнение для всех не отобразятся):
find . -perm a=r+w
Поиск файлов по владельцу
Можно также найти файлы, принадлежащие определённому пользователю.
Вот как обнаружить в текущей папке все файлы пользователя Джона:
find . -type f -user John
Эта опция сочетается с другими, будь то размер или время и имя файла:
find . -type f -user John -name "*.cpp"
Отключение рекурсивного поиска для поиска только в текущей папке
По умолчанию команда find выполняет поиск во всех подпапках текущего расположения. Если это не требуется, можно ограничить глубину поиска значением «1». Так вы ограничитесь поиском в текущей папке, не залезая в подпапки.
find . -maxdepth 1 -type f -name "*.txt"
Исключение папки из поиска
Если нет необходимости производить поиск в той или иной папке, можно исключить её с помощью опций path, prune и логического «или».
Будьте внимательны: путь к папке должен оканчиваться на *, затем идёт
-prune и только потом
-o.
Попросту говоря, при поиске с опцией prune папка, указанная с помощью path, игнорируется. Prune всегда сопровождается флагом
-o (логическое «или»), чтобы папки, которые не были исключены, просматривались на наличие искомого объекта.
Дальнейшая работа с результатами команды find: exec и xargs
Итак, мы изучили различные способы поиска файлов по заданным параметрам. Это хорошо. А теперь следующий шаг: рассмотрим, какие действия можно выполнять с результатами команды find.
Например, как найти файлы с именем, соответствующим определённому шаблону, и переименовать их за одно действие? Или выявить и удалить пустые файлы?
Вам уже известно, что в Linux можно использовать
перенаправление ввода-вывода, чтобы объединить результаты одной команды с вводом другой. Но с результатами команды find это не сработает — по крайней мере, не напрямую.
Чтобы выполнить действия над результатом команды find, есть два варианта:
Применить exec
Применить xargs
Использование find и exec
Допустим, вам нужен подробный список (ls -l) файлов, найденных командой find. Вот как его получить:
find . -type f -name *.txt" -exec ls -l {} +
Результат будет таким:
abhishek@LHB:~/Examples$ find . -type f -name "*.txt" -exec ls -l {} +
-rw-rw-r-- 1 abhishek abhishek 39 Oct 13 19:30 ./another.txt
-rw-rw-r-- 1 abhishek abhishek 35 Oct 13 15:36 ./new/dir1/new.txt
-rw-rw-r-- 1 abhishek abhishek 35 Oct 13 15:36 ./new/dir2/another.txt
-rw-rw-r-- 1 abhishek abhishek 35 Oct 13 18:51 ./new/mystuff/new.txt
-rwxrwxrwx 1 abhishek abhishek 35 Oct 13 15:37 ./new/new.txt
-rw-rw-r-- 1 abhishek abhishek 35 Oct 13 18:16 ./new.txt
Многие забывают ввести
{} + в конце команды exec. Но это необходимо — как и пробел между скобками {} и плюсом +.
Фигурные скобки ссылаются на результат выполнения команды find. Их содержимое может иметь следующий вид: {файл 1, файл 2, файл 3}. Символ
+ используется как конец команды exec.
Есть ещё один вариант оформления exec:
find . -type f -name *.txt" -exec ls -l {} \;
В данном случае плюс заменён на точку с запятой. Дополнительная косая черта означает, что точка с запятой не является специальным символом.
Преимущество сочетания
{} + заключается в меньшем количестве команд (
ls -l file1 file2 file3), тогда как комбинация
{} \; запустит цепочку
ls -l file1,
ls -l file2 и так далее.
Однако сочетание
{} \; даёт возможность использовать
{} несколько раз в одном и том же выражении exec. Так, приведённая ниже команда переименует все обнаруженные файлы с расширением .old.
find . -type f -name *.txt" -exec mv {} {}.old \;
Использование команды xargs
Многие пользователи Linux сталкиваются с необходимостью перенаправления ввода-вывода довольно часто. Но команда exec с цепочкой символов
{} + кажется им слишком сложной.
И тут на помощь приходит xargs. Нужно просто перенаправить вывод команды find в
команду xargs через конвейер.
find . -type f -name *.txt" | xargs ls -l
Синтаксис куда проще, верно? К тому же команда xargs тоже весьма эффективна. Подробнее о ней — в статье по
ссылке.
Сочетание команд find и grep
Теперь вы умеете совмещать команду find с xargs и exec, и пора перейти на следующий уровень — объединить find и grep.
Для сисадминов и разработчиков комбинация команд find и grep — одна из самых распространённых и вместе с тем самых полезных.
Команда find находит файлы с именем, соответствующим шаблону, а затем команда grep выполняет поиск по их содержимому.
Например, вам нужно найти все файлы .txt, в которых есть имя «Alice». Объединить команды find и grep можно так:
find . -type f -name "*.txt" -exec grep -i alice {} +
А можно с помощью xargs:
find . -type f -name "*.txt" | xargs grep -i alice
Конечно, пример элементарный, но если
команда grep вам знакома, можете использовать её на своё усмотрение.
И это далеко не все возможности команды find...
Перечислить все опции и примеры использования команды find практически невозможно. Её возможностям нет границ, но если вы освоите её принципы, она окажется очень кстати во многих ситуациях. Решающий фактор — как сочетается логика действия разных опций и команд.