Я слышал, как люди спрашивали, в чем разница между grep и find, несколько раз за последние несколько лет. Мне это казалось очевидным, но, возможно, это не так, если вы только начинаете работать с Linux.

В чем разница между командами grep и find?

Find — это утилита для поиска файлов и каталогов в файловой системе Linux на основе определенных критериев (например, имени файла, даты изменения, размера, типа файла и т. д.), grep — это утилита для поиска шаблонов в содержимом файлов или в выводе других команд.

Разница может быть незначительной, если у вас нет большого опыта работы с Linux.

Другими словами, find возвращает файлы и каталоги в файловой системе на основе ваших критериев поиска (например, на основе их имени), тогда как grep возвращает файлы, содержимое которых соответствует искомому шаблону.

Давайте разберем это более подробно на нескольких примерах!

Команда Find: поиск файлов по имени

Я хочу найти файл findme.txt в моей системе Linux, но не знаю точного каталога этого файла.

Это прекрасная возможность использовать команду find, которая, как упоминалось в предыдущем разделе, позволяет находить файлы и каталоги в Linux на основе определенных критериев.

В этом случае критерием является соответствие имени файла «findme.txt».

Общий синтаксис команды find согласно ее руководству выглядит следующим образом:

find PATH [EXPRESSION]

Проще говоря…

find WHERE [WHAT]

Что именно делает команда find при запуске?

Он рекурсивно просматривает дерево каталогов для каждого предоставленного пути и возвращает файлы или каталоги, соответствующие ВЫРАЖЕНИЮ.

Тот факт, что ВЫРАЖЕНИЕ заключено в квадратные скобки, указывает на то, что выражение является необязательным.

Легче понять на примере…

Я создал тестовый каталог (названный example) в /var/tmp. Это вывод команды find, где path — /var/tmp/example/:

[myuser@localhost example]$ find /var/tmp/example/
/var/tmp/example/
/var/tmp/example/example_file2
/var/tmp/example/example_file3
/var/tmp/example/example_dir2
/var/tmp/example/example_dir1
/var/tmp/example/example_file1

В выводе команды find я вижу все файлы и подкаталоги внутри каталога /var/tmp/example.

Теперь давайте добавим ВЫРАЖЕНИЕ для фильтрации вывода на основе имени *file1 (выражение, которое мы используем для выбора вывода, поступающего от команды find, также может содержать подстановочные знаки).

Выражение также содержит флаг -name, позволяющий фильтровать имена файлов и каталогов, найденных командой find:

[myuser@localhost example]$ find /var/tmp/example/ -name *file1
/var/tmp/example/example_file1

Как видите, на этот раз команда find возвращает только файл /var/tmp/example/example_file1.

Часть выражения команды может быть использована для фильтрации вывода команды find на основе других критериев. Вот несколько примеров:

  • Время модификации
  • Размер
  • Разрешения
  • Тип (например, обычный файл, каталог, сокет, канал имен и т. д.)

Команда find позволяет находить файлы и каталоги в файловой системе Linux на основе критериев поиска, указанных пользователем.

Команда grep: поиск шаблонов внутри файлов

Теперь давайте посмотрим, как работает команда grep.

Команда grep может находить шаблоны внутри содержимого файлов. Если вы хотите узнать, какие файлы в вашей файловой системе соответствуют определенной строке, команда grep — это ответ на этот вопрос.

Синтаксис команды grep:

grep [OPTIONS] PATTERN FILE

Возвращаясь к файлам и подкаталогам, которые я создал в /var/tmp/example/, я добавил строку FINDME внутрь одного из файлов.

Вот как можно узнать, какой из них нужен, с помощью команды grep:

[myuser@localhost example]$ pwd
/var/tmp/example
[myuser@localhost example]$ grep FINDME *
grep: example_dir1: Is a directory
grep: example_dir2: Is a directory
example_file2:FINDME

Последняя строка показывает, что файл example_file2 содержит строку FINDME.

Я использовал команду:

grep FINDME *

Где FINDME — это ШАБЛОН, а * (подстановочный знак, обозначающий все файлы) — это часть команды ФАЙЛ.

В выводе вы также можете увидеть следующие строки:

grep: example_dir1: Is a directory
grep: example_dir2: Is a directory

Чтобы избежать этой ошибки и убедиться, что grep выполняет рекурсивный поиск внутри каждого подкаталога, мы можем использовать флаг -r.

Команда становится такой:

[myuser@localhost example]$ grep -r FINDME *
example_dir1/example_file4:FINDME
example_file2:FINDME

Как видите, благодаря флагу -r grep также может найти соответствующий файл в каталоге example_dir1.

Имеет ли это смысл?

Давайте подведем итоги…

Команда grep позволяет искать файлы в файловой системе Linux, содержащие определенный шаблон в своем содержимом.

ШАБЛОН, который мы использовали в нашем примере, очень прост (слово FINDME). Сила команды grep в том, что ШАБЛОН может быть любым сложным регулярным выражением, которое захочет пользователь.

Фильтрация вывода find с помощью команды grep

Я знаю, что эта статья о разнице между grep и find.

Но я подумал…

…как их можно использовать вместе?

Если две вещи различны, это не значит, что они не могут хорошо работать вместе (это можно применить ко многим сферам жизни! 😀 )

В нашем примере grep мы увидели, как использовать фильтр -name как часть ВЫРАЖЕНИЯ.

Как мне заменить его с помощью команды grep?

(вот пример, о котором я говорю)

[myuser@localhost example]$ find /var/tmp/example/ -name *file1
/var/tmp/example/example_file1

Вместо этого я мог бы использовать pipe и команду grep!

[myuser@localhost example]$ find /var/tmp/example/ | grep file1
/var/tmp/example/example_file1

Интересно, у меня получился точно такой же результат!

Как это работает?

Канал используется в Linux для отправки выходных данных команды слева на входные данные команды справа.

В этом случае вывод команды find используется в качестве входных данных для команды grep.

Итак, команда grep получает следующий вывод от find:

[myuser@localhost example]$ find /var/tmp/example/
/var/tmp/example/
/var/tmp/example/example_file2
/var/tmp/example/example_file3
/var/tmp/example/example_dir2
/var/tmp/example/example_dir1
/var/tmp/example/example_dir1/example_file4
/var/tmp/example/example_file1

И возвращает только те строки, которые соответствуют PATTERN file1.

Это очень удобно и может быть применено ко всем командам Linux. Очень мощно!

Еще один способ объединить Find и Grep в Linux

Есть еще одна комбинация, в которой find и grep могут работать вместе.

Часть EXPRESSION команды find также может содержать флаг -exec, который позволяет применять другие команды Linux к каждому файлу, идентифицированному find.

Таким образом, find выполняет фильтрацию на основе атрибутов файлов, а затем grep добавляет еще один уровень фильтрации на основе содержимого файлов.

Например, я могу найти файлы с определенным именем с помощью find, а затем проверить, какой из этих файлов содержит определенный ШАБЛОН, с помощью grep.

Следующая команда использует find для поиска файлов, имя которых содержит example_file, а затем использует grep для получения всех файлов, содержащих строку «I’M HERE» внутри своего содержимого.

[myuser@localhost example]$ find /var/tmp/example/ -name '*example_file*' -exec grep -H "I'M HERE" {} \;
/var/tmp/example/example_file2:I'M HERE
/var/tmp/example/example_dir1/example_file4:I'M HERE

Флаг -H, переданный команде grep, выводит имя файла для каждого совпадения. Без флага -H вывод был бы таким:

[myuser@localhost example]$ find /var/tmp/example/ -name '*example_file*' -exec grep "I'M HERE" {} \;
I'M HERE
I'M HERE

Кроме того, я знаю, что синтаксис части -exec выражения grep не очень прост для чтения и запоминания, особенно если вы видите его впервые.

find... -exec COMMAND {} \;

Заключение

В этой статье вы узнали разницу между командами grep и find в Linux.

Каким-то образом они оба работают с файлами, но find может искать файлы на основе их атрибутов (имя файла, права доступа, размер, время изменения, тип и т. д.), а grep может идентифицировать файлы, содержимое которых соответствует определенным шаблонам.

Две совершенно разные вещи!

Мы также увидели, что find и grep могут очень хорошо работать вместе в следующих случаях:

  • Использование канала для отправки вывода команды find на вход команды grep.
  • Использование выражения -exec для применения фильтрации grep ко всем файлам, идентифицированным командой find.

На этом статья закончена!

Теперь пришло ваше время!

Как вы используете grep и find, будучи пользователями Linux или в своих скриптах Bash?

Written by Иван Васильков

Системный администратор и DevOps с опытом 10+ лет.