Всем доброго времени суток и всяческих таких прочих разностей.
Давно что-то я ничего не писал на серверную тему в блоговую часть сайта. Сегодня немного привычных и унылых, для многих опытных человеков, банальностей, но при этом немного полезного инструментария для всех остальных.
Как Вы уже поняли из заголовка речь пойдет про команды find и grep в Linux, которые позволяют используя консоль, терминал, ssh или что там у Вас еще (или как Вы это “еще” называете) искать файлы/директории по их именам/содержимому и тому подобному.
Давайте кратенько посмотрим на них.
-
find – синтаксис и зачем оно нужно
-
find примеры использования
-
grep – что это и зачем может быть нужно
-
grep примеры использования
-
Послесловие
find – синтаксис и зачем оно нужно
find — утилита поиска файлов по имени и другим свойствам, используемая в UNIX‐подобных операционных системах. С лохматых тысячелетий есть и поддерживаться почти всеми из них.
Базовый синтаксис ключей (забран с Вики):
- -name — искать по имени файла, при использовании подстановочных образцов параметр заключается в кавычки. Опция `-name‘ различает прописные и строчные буквы; чтобы использовать поиск без этих различий, воспользуйтесь опцией `-iname‘;
- -type — тип искомого: f=файл, d=каталог, l=ссылка (link), p=канал (pipe), s=сокет;
- -user — владелец: имя пользователя или UID;
- -group — владелец: группа пользователя или GID;
- -perm — указываются права доступа;
- -size — размер: указывается в 512-байтных блоках или байтах (признак байтов — символ «c» за числом);
- -atime — время последнего обращения к файлу (в днях);
- -amin — время последнего обращения к файлу (в минутах);
- -ctime — время последнего изменения владельца или прав доступа к файлу (в днях);
- -cmin — время последнего изменения владельца или прав доступа к файлу (в минутах);
- -mtime — время последнего изменения файла (в днях);
- -mmin — время последнего изменения файла (в минутах);
- -newer другой_файл — искать файлы созданные позже, чем другой_файл;
- -delete — удалять найденные файлы;
- -ls — генерирует вывод как команда ls -dgils;
- -print — показывает на экране найденные файлы;
- -print0 — выводит путь к текущему файлу на стандартный вывод, за которым следует символ ASCII NULL (код символа 0);
- -exec command {} ; — выполняет над найденным файлом указанную команду; обратите внимание на синтаксис;
- -ok — перед выполнением команды указанной в -exec, выдаёт запрос;
- -depth или -d — начинать поиск с самых глубоких уровней вложенности, а не с корня каталога;
- -maxdepth — максимальный уровень вложенности для поиска. «-maxdepth 0» ограничивает поиск текущим каталогом;
- -prune — используется, когда вы хотите исключить из поиска определённые каталоги;
- -mount или -xdev — не переходить на другие файловые системы;
- -regex — искать по имени файла используя регулярные выражения;
- -regextype тип — указание типа используемых регулярных выражений;
- -P — не разворачивать символические ссылки (поведение по умолчанию);
- -L — разворачивать символические ссылки;
- -empty — только пустые каталоги.
Примерно тоже самое, только больше и в не самом удобочитаемом виде, т.к надо делать запрос по каждому ключу отдельно, можно получить по
find -help
Результатам будет нечто такое из чего можно вычленять справку по отдельному ключу или команде (кликабельно):
В качестве развлечения можно использовать:
man find
Дабы получить мануал из самой системы по базису и ключам (тоже кликабельно);
Немного о примерах использования. Точно так же, оттуда же и тп. Просто для понимания как оно работает вообще. Наиболее просто, конечно, осознать это потренировавшись в той же консоли на реальной системе.
к содержанию ↑
find примеры использования
Ищем все файлы, начиная с текущей директории, название которых начинается на sonikelf:
find . -name 'sonikelf*'
Найти все файлы, начиная с корневой директории, название которых начинается на sonikelf:
find / -name 'sonikelf*'
Поиск в директориях /usr/local/man и /opt/local/man файлов, название которых начинается на sonikelf:
find /usr/local/man /opt/local/man -name 'sonikelf*'
Ищем все файлы, начиная с текущей директории, название которых начинается на sonikelf или qu. Обратите внимание, что по умолчанию все аргументы соединены с помощью логического и (опция ‘-a‘). Если необходимо объединить несколько аргументов логическим или — используйте ключ ‘-o‘:
find . ( -name "sonikelf*" -o -name "qu*" ) -print
Ищем графические файлы, начиная с текущего каталога (см.на кавычки):
find . -type f -regex ".*.(jpg|jpeg|gif|png|JPG|JPEG|GIF|PNG)"
Вывести список файлов (см. на / ) во всей файловой системе, чей размер больше 100 Мб:
find / -size +100M -print
Ищем файлы в указанных каталогах:
find /var/spool/postfix/{deferred,active,maildrop,incoming}/ -type f
Еще примеров можно поискать тут, так или здесь. Да тысячи их, но проще попрактиковаться самому, используя –help для нужного запроса и поиск в необходимой директории.
к содержанию ↑
grep – что это и зачем может быть нужно
Про “репку” (как я её называю) почему-то в курсе не многие, что печалит. “Унылая” (не в обиду) формулировка из Википедии звучит примерно так:
grep — утилита командной строки, которая находит на вводе строки, отвечающие заданному регулярному выражению, и выводит их, если вывод не отменён специальным ключом.
Не сильно легче, но доступнее, можно сформулировать так:
grep — утилита командной строки, используется для поиска и фильтрации текста в файлах, на основе шаблона, который (шаблон) может быть регулярным выражением.
Если всё еще ничего не понятно, то условно говоря это удобный поиск текста везде и всюду, в особенности в файлах, директория в и тп. Удобно распарсивать логи и их содержимое, не прибегая к софту, как это бывает в Windows.
Справку можно вычленить так же как по find, т.е методом pgrep, fgrep, egrep и черт знает что еще:
man grep
Или:
help grep
Расписывать все ключи и даже основные тут (вы еще помните, что это блоговая часть сайта?) не буду, так как в отличии от find‘а, последних тут вообще страшное подмножество, особенно учитывая, что существуют pgrep, fgrep, egrep и черт знает что еще, которые, в некотором смысле тоже самое, но для определенных целей.
Потрясающе удобная штука, которая жизненно необходима, особенно, если Вы что-то когда-то где-то зачем-то администрировали. Взглянем на примеры.
к содержанию ↑
grep примеры использования
В принципе для работы grep не обязательно указывать даже файл или директорию, но это крайне желательно, если Вы хотите найти всё быстрее и точнее. Например:
grep sonikelf
Найдет файлы с упоминанием меня любимого, если таковые есть. Точнее не файлы, а строки с упоминанием указанного слова, т.е в данном случае sonikelf. Здесь стоит упомянуть, что строкой grep считает все символы, находящиеся между двумя символами новой строки.
grep sonikelf file.txt | поиск sonikelf в файле file.txt, с выводом полностью совпавшей строкой |
grep -o sonikelf file.txt | поиск sonikelf в файле file.txt и вывод только совпавшего куска строки |
grep -i sonikelf file.txt | игнорирование регистра при поиске |
grep -bn sonikelf file.txt | показать строку (-n) и столбец (-b), где был найден sonikelf |
grep -v sonikelf file.txt | инверсия поиска (найдет все строки, которые не совпадают с шаблоном sonikelf) |
grep -A 3 sonikelf file.txt | вывод дополнительных трех строк, после совпавшей |
grep -B 3 sonikelf file.txt | вывод дополнительных трех строк, перед совпавшей |
grep -C 3 sonikelf file.txt | вывод три дополнительные строки перед и после совпавшей |
grep -r sonikelf $HOME | рекурсивный поиск по директории $HOME и всем вложенным |
grep -c sonikelf file.txt | подсчет совпадений |
grep -L sonikelf *.txt | вывести список txt-файлов, которые не содержат sonikelf |
grep -l sonikelf *.txt | вывести список txt-файлов, которые содержат sonikelf |
grep -w sonikelf file.txt | совпадение только с полным словом sonikelf |
grep -f sonikelfs.txt file.txt | поиск по нескольким sonikelf из файла sonikelfs.txt, шаблоны разделяются новой строкой |
grep -I sonikelf file.txt | игнорирование бинарных файлов |
grep -v -f file2 file1 > file3 | вывод строк, которые есть в file1 и нет в file2 |
grep -in -e ‘python’ `find -type f` | рекурсивный поиск файлов, содержащих слово python с выводом номера строки и совпадений |
grep -inc -e ‘test’ `find -type f` | grep -v :0 | рекурсивный поиск файлов, содержащих слово python с выводом количества совпадений |
grep . *.py | вывод содержимого всех py-файлов, предваряя каждую строку именем файла |
grep “Http404” apps/**/*.py | рекурсивный поиск упоминаний Http404 в директории apps в py-файлах |
И так далее и тому подобное. Потрясающе доступный с точки зрения простоты чтения и понимания, мануал по grep’у есть например тут. Ну либо у буржуев, как и всегда (если Вы знаете английский).
к содержанию ↑
Послесловие
Ну в двух словах как-то так. Быть может кто-то еще не знал, не умел или подзабыл и может быть пригодится кому-то зачем-то и где-то.
Как и всегда, если есть вопросы и, особенно, дополнения (разумные, адекватные и по делу), то добро пожаловать в комментарии к этой заметке.
В статье про поиск файлов и папок мы говорили про команду find и том, как ее использовать на сервере для оптимального поиска чего-либо. Но в арсенале системного администратора Linux-сервера также имеется команда под названием grep, про которую сегодня хочу рассказать читателям и подписчикам. Давайте познакомимся с ней, поймем в чем разница между find и grep и когда лучше использовать каждую команду.
Поиск файлов и папок через терминал в Linux-дистрибутивах
Не забываем также подписаться на обновления канал Просто Код в телеграме. Так вы будете получать уведомления о новых постах быстрее, чем уведомляет об этом Дзен.
Что делает команда GREP?
GREP расшифровывается как Global Regular Expression Print, что говорит о том, что она используется для поиска строк и шаблонов в группе файлов или папок, а также среди данных, которыми оперируют другие команды и процессы на сервере. Как это часто бывает в Linux, это не просто название команды, а отдельная системная и консольная утилита. В основе работы утилиты лежит расширенный синтаксис регулярных выражений, который появился в UNIX-системах 1981 году. GREP встречается во всех дистрибутивах Linux.
Синтаксис команды
Познакомимся с синтаксисом (то есть, правилами написания) команды grep.
grep [опции] [регулярное выражение] [место поиска – файл или директория]
Но чаще всего grep используется в качестве команды, которой передают «выхлоп» (то есть, результат работы) другой команды для фильтрации и конечного вывода в терминал.
Фильтруем «выхлоп» других команд
Вспомним про команду ls, которая выводит списком содержимое директории. В тестовом примере ниже у меня есть папка Test, внутри которой есть как файлы, так и папки. Файлы имеют имя File<набор_символов>, папки названы как Folder<набор_символов>. Мне нужно показать только папки и единственное, что я помню – это то, что каждая папка имеет имя Folder. Воспользуемся командами ls и grep, чтобы реализовать задуманное
ls | grep Folder
Символ прямой черты | еще называют «трубкой», он принимает выходные данные одной команды и передает их следующей в качестве входных данных. То есть, мы передали «выхлоп» команды ls в качестве входных данных команде grep, которая отфильтровала результаты и показала только то, что содержит в имени Folder. В моем примере папок всего четыре, но представьте, если бы их было несколько десятков и сотен – тогда бы подобная фильтрация сильно сэкономила время.
В следующем примере нам нужны и файлы, и папки, которые имеют в имени какую-либо постоянную часть. Это может быть имя сервера, дата бэкапа и пр.
ls | grep ABC
Ну, и наконец, более практичный пример. Очень часто на сервере нужно посмотреть какой порт «прослушивается» каким-либо процессом или программой. Для этого тоже можно использовать команду grep, чтобы отфильтровать значения до нужных. В команде ниже я вывожу порты, которые слушает протокол ssh.
sudo netstat -lntup | grep “ssh”
Поиск строк в файлах
Представим ситуацию, что у вас есть папка с сайтом. И внутри множества файлов этого сайта нужно найти конкретное слово. Не вручную же перебирать все файлы! Для этого тоже можно использовать команду grep. Например, среди пяти файлов в папке Test попробуем найти те, где используется слово «grep»:
grep -R “grep” Test
Если нам необходимо объединить выражения и осуществить поиск нескольких строк, то нужно использовать ключ -e. Это своего рода указание «или» для утилиты. Попробуем найти среди наших файлов те, где встречаются слова «grep» или «php»:
grep -R -e “grep” -e “php” Test
Также вместо папки мы можем указать имя конкретного файла (убрав перед этим ключ -R) и попытаться найти нужные строки в нем.
grep “grep” <имя_файла>
Если в файле не будет ничего найдено, то команда вернет пустую строку.
Для расширения возможностей поиска строк в файлах можно использовать следующие ключи и так называемые якоря:
- grep -i – поиск без учета регистра
- grep -w – поиск по всему слову
- grep -v – обратный поиск (то есть, он вернет все, что не соответствует заданной после строке)
- grep -r -L – вернет имена файлов, в которых отсутствует заданный после шаблон для поиска
- grep -n – выведет не просто найденную строку, но и укажет ее номер в документе
- grep -A<количество> – выводит найденную строку и следующую строку после совпадения, количество выводимых строк можно менять
- grep -B<количество> – выводит найденную строку и предыдущую строку до совпадения, количество выводимых строк можно менять
- grep -C<количество> – выводит найденную строку и строки до и после совпадения, количество выводим строк можно менять
- grep -q – запуск команды в тихом режиме, после выполнения она просто сохранит код статуса в системной переменной $? (если 0, то совпадения есть, если 1, то совпадений нет); такой метод используют в скриптах для проверки условий, когда не нужно выводить конкретную заданную строку.
- grep “^” – якорь ^ говорит, что совпадение должно быть в начале строки
- grep “$” – якорь $ говорит, что совпадение должно быть в конце строки
- grep “<” – якорь < привязывает совпадение к началу слов
- grep “>” – якорь > привязывает совпадение к концу слов
Поиск при помощи регулярных выражений (regular expression)
По-настоящему функционал grep раскрывается при использовании регулярных выражений. Раскрыть возможности их использования в одной статье невозможно, поэтому думаю, что работе с регулярными выражениями можно посвятить отдельную статью. Давайте договоримся о том, что если такая статья вам интересна, то вы поставите этому посту лайк и как только их наберется 15 штук, я подготовлю материал по regular expression.
Отличия grep и find
Отличия между двумя командами следующие:
- команду grep лучше использовать для поиска содержимого внутри файлов и папок, тогда как find идеально подойдет если вы желаете найти сам файл или папку (она и найдет, и путь нужный выведет).
- команда find используется для поиска полных имен файлов и папок в системе, тогда как grep лучше использовать для нечеткого запроса (если уж вы все же решитесь искать файлы и папки с помощью grep)
- команда find использует для поиск стандартные (системные) шаблоны, тогда как в grep такие шаблоны может задавать пользователь
Итог
Тема использования grep обширна, на самом деле, там есть огромное количество полезных штук, лишь только часть из них я показал в рамках материала. Задача статьи – не рассказать про grep ВСЕ, а познакомить новичков с этой утилитой и мотивировать ее изучать и использовать на практике. Думаю, что в комментариях опытные подписчики и читатели смогут дополнить материал нужной информацией и конкретными примерами использования grep.
Давайте же поддержим канал подпиской, лайком и комментариями, ведь чем больше активности вы проявляете, тем чаще алгоритмы Дзена показывают посты в ленте рекомендаций.
Если не подписались на уведомления канала в Телеграм, то самое время сделать это, ведь информация о новых заметках приходит там сразу в момент публикации!
Иногда может понадобится найти файл, в котором содержится определённая строка или найти строку в файле, где есть нужное слово. Это может понадобится для поиска логов, поиска конфигурационных файлов, если вы не знаете где они находятся или для поиска файлов с программным кодом.
Раньше для этих целей использовалась только утилита grep, однако сейчас существует огромное количество других программ, которые могут делать это быстрее и предоставляют более удобный интерфейс. В этой статье мы рассмотрим самые интересные из них и несколько примеров как ими пользоваться.
Все утилиты в этой статье работают только в терминале. Если вас интересуют приложения с графическим интерфейсом, посмотрите статью поиск файлов в Linux. Большинство описанных ниже команд имеют примерно одинаковый синтаксис:
$ команда опции паттерн /путь/к/папке
Паттерн для поиска может быть обычным словом, но большинство команд ожидают, что это будет регулярное выражение, поэтому если в вашем запросе есть спец. символы, вы можете получить в результате не то, что ожидаете. Путь к папке, как правило, указывать не обязательно, тогда команды используют текущую папку для поиска. А теперь давайте рассмотрим каждую команду подробнее.
1. Grep
Прежде чем перейти к современным утилитам, давайте рассмотрим команду grep. Она входит в набор программ GNU и используется для поиска строк в файлах и файлов по их содержимому уже очень давно.
По умолчанию grep фильтрует один файл или стандартный ввод. Для того чтобы выполнять поиск в папке по нескольким файлам, нужно включить рекурсивный поиск с помощью опции -r. Например, найдем все файлы в папке /etc/, которые содержат строку root:
sudo grep -r "root" /etc/
Команда grep не подсвечивает вхождения символов которое вы искали цветом, для этого можно использовать опцию –color=always. Но в большинстве дистрибутивов эта опция уже прописана в алиасе для этой команды, поэтому вывод будет выглядеть вот так:
sudo grep --color=always -r "root" /etc/
С помощью опции -С или –context вы можете включить отображение не только текущей строки, в которой было найдено вхождение но и нескольких строк до и после. В этом параметре надо указать количество строк для отображения:
sudo grep -r -С2 "root" /etc/
По умолчанию grep ожидает, что поисковый запрос может быть регулярным выражением, но поддерживается только базовый синтаксис. Для включения расширенного синтаксиса нужно использовать опцию -E. Например, для того чтобы найти все файлы содержащие переменные, начинающиеся на букву A в папке /etc/ выполните:
sudo grep -r -E "^A[A-Z_]+=" /etc/
А для того чтобы искать именно фиксированную строку, а не регулярное выражение используйте опцию -F или команду fgrep. Например, так можно найти все файлы содержащие секцию [Install] в папке /usr/:
sudo grep -r -F "[Install]" /usr/
2. Ripgrep
Это популярная альтернатива grep написанная на Rust. Она может делать всё то же самое что и grep, но быстрее, а ещё её гораздо удобнее использовать. Рекурсивный поиск включён по умолчанию, и подсветка вхождений и имени файла разными цветами тоже работает без дополнительных опций, а также она пропускает скрытые файлы, бинарные файлы и файлы, перечисленные в .gitignore. Для установки ripgrep в Ubuntu используйте такую команду:
sudo apt install ripgrep
Если вы выполните команду, указав путь к файлу, то она найдёт и отобразит все вхождения искомого слова в этом файле. Например:
sudo rg root /etc/passwd
Если же передать папку, то команда будет искать во всех файлах, которые находятся в этой папке. По умолчанию используется текущая папка. Например, для того чтобы найти все файлы, содержащие слово “root” в каталоге /etc/ используйте такую команду:
sudo rg root /etc/
Также, как и при использовании grep, можно отобразить не только строку со вхождением но и несколько строк до и после. Например, по две:
sudo rg -C2 root /etc/
А вот полный синтаксис регулярных выражений здесь работает по умолчанию. Например:
sudo rg "^A[A-Z_]+=" /etc/
Если же вы хотите указать что надо искать именно строку, а не регулярное выражение, используйте опцию -F:
sudo rg -F "[Install]" /usr/
3. Ack
Если вам нужно найти файл с исходным кодом зная строку, которая в нём есть, то для этого существуют более подходящие утилиты чем grep. Например, ack. Она появилась уже довольно давно и предназначена именно для работы с исходным кодом. Кроме всех возможностей grep она позволяет пропускать файлы резервных копий, внутренние файлы репозиториев .git и .svn, а также дампы памяти. Кроме того, вы можете выбрать типы файлов, в которых будет выполняться поиск и даже указать определённую часть файла. Для установки программы в Ubuntu используйте такую команду:
sudo apt install ack
Самый простой пример – поиск всех файлов содержащих слово root в папке /etc/:
sudo ack "root" /etc/
Или же регулярное выражение, как в предыдущем разделе для поиска файлов с переменными, начинающимися на букву A:
sudo ack "^A[A-Z_]+=" /etc/
Для того чтобы вывести не только строку с вхождением, но и строки до и после неё используйте опцию -C. По умолчанию выводится по две строки:
sudo ack -C "root" /etc/
Команда ack позволяет указать тип файлов, в которых надо выполнять поиск. Это очень удобно для поиска по исходникам. Вы можете выбрать только исходные файлы Си, JavaScript или PHP и так далее. Все доступные типы файлов можно посмотреть с помощью команды:
ack --help-types
Например, для того чтобы выполнять поиск только в XML файлах используйте опцию –type со значением xml:
sudo ack --type=xml "root" /etc/
Ещё одна интересная возможность утилиты ack – настройка частей файла, в которых будет выполняться поиск с помощью регулярного выражения. Для этого предназначены опции –range-start и –range-end и это будет работать как в рамках одной строки так и в рамках всего файла. Например, для поиска только в комментариях XML файлов можно использовать такую команду:
sudo ack --type=xml --range-start="<!--" --range-end="-->" "root" /etc/
4. Sliver Searcher
На данный момент это одна из самых популярных программ для поиска текста по файлам в Linux. Она была спроектирована в качестве альтернативы для ack, как инструмент для поиска кода. В дополнение к основным возможностям ack, она значительно быстрее и учитывает настройки исключений из файлов .gitignore и .hgignore. Для установки программы в Ubuntu используйте такую команду:
sudo apt install silversearcher-ag
Рассмотрим тот же пример, что и в предыдущих разделах. Для того чтобы найти все файлы содержащие слово root в папке /etc/ выполните:
sudo ag "root" /etc/
Аналогично grep и ripgrep, ag ожидает регулярное выражение в качестве паттерна поиска, поэтому вы можете использовать его без каких либо дополнительных опций. Например:
sudo ag "^A[A-Z_]+=" /etc/
Но если вы хотите чтобы поисковый запрос рассматривался именно как строка, используйте опцию -Q. Например, для поиска всех файлов, содержащих секцию [Install] в папке /usr/ выполните:
sudo ag -Q "[Install]" /usr/
Здесь тоже можно вывести несколько строк до и после строки со вхождением с помощью опции -С.
В отличие от grep и ripgrep, команда ag позволяет указать тип файлов в которых вы хотите выполнять поиск. Посмотреть все доступные типы файлов можно с помощью такой команды:
ag --list-file-types
Например, для того чтобы искать только по ini файлам используйте такую команду:
sudo ag --ini "root" /etc/
Утилита также позволяет использовать регулярное выражение для фильтрации файлов по имени перед тем как выполнять поиск по содержимому. Для этого нужно использовать опцию -G. Например для того чтобы выполнять поиск только по файлам, имя которых заканчивается на conf, выполните:
sudo ag -G .*.conf$ root /etc/
5. Skim
Это ещё одна интересная утилита для нечеткого поиска в реальном времени, написанная на Rust. По умолчанию она ищет файлы по имени, но её можно использовать вместе с одной из выше перечисленных утилит для поиска файлов по содержимому в реальном времени. Пакета с программой пока нет в официальных репозиториях, но вы можете установить её с помощью cargo:
cargo install skim
Команда выполняет поиск только в текущей папке и указать другую папку нельзя, поэтому нужно сначала перейти в нужную папку используя команду cd. Например:
cd /etc/
Затем используйте такую команду для того чтобы объединить sk с Silver Searcher для фильтрации файлов по содержимому:
sk --ansi -i -c 'ag --color "{}"'
Здесь опция –ansi включает отображение цветов, -i включает интерактивный режим, а опция -c задает команду, которая будет выполнена при вводе какого-либо запроса, строка {} будет заменена на то, что вы введете при поиске. Просто выполните команду и начинайте вводить слово которое хотите искать:
Дальше вы можете использовать все функции фильтрации нечеткого поиска для обработки результатов.
Производительность grep, rg, ack и ag
Перед завершением статьи хочу привести небольшой тест производительности выше перечисленных утилит для поиска текста по файлам в Linux. Я скачал и распаковал исходники ядра Linux версии 6.2.10, а затем использовал каждую из утилит для того чтобы найти все файлы, которые содержат слово ext4 и btrfs. Между разными утилитами система перезагружалась, для того чтобы исключить влияние кэша. Вот результаты:
Команда | Время, с | Команда | Время, с |
grep -r ext4 ./ | 23.167 | grep -r btrfs ./ | 3.860 |
rg ext4 ./ | 27.164 | rg btrfs ./ | 1.387 |
ack ext4 ./ | 36.141 | ack btrfs ./ | 7.206 |
ag ext4 ./ | 24.594 | ag btrfs ./ | 3.158 |
Как видите, сразу после запуска системы все команды работают примерно одинаково. Однако после того, утилиты, написанные на Rust эффективнее используют кэш, поскольку при повторных запусках для того же набора файлов работают быстрее аналогов на Си.
Выводы
В этой статье были рассмотрены самые часто используемые утилиты для поиска файлов по содержимому и поиска текста в файлах в Linux. Как видите, существует достаточно инструментов чтобы было из чего выбрать. Все команды довольно похожие, но каждая из них имеет свои особенности. А что используете вы? Напишите в комментариях!
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .
grep
stands for Globally Search For Regular Expression and Print out. It is a command line tool used in UNIX and Linux systems to search a specified pattern in a file or group of files.
grep
comes with a lot of options which allow us to perform various search-related actions on files. In this article, we’ll look at how to use grep
with the options available as well as basic regular expressions to search files.
Without passing any option, grep
can be used to search for a pattern in a file or group of files. The syntax is:
grep '<text-to-be-searched>' <file/files>
Note that single or double quotes are required around the text if it is more than one word.
You can also use the wildcard (*) to select all files in a directory.
The result of this is the occurences of the pattern (by the line it is found) in the file(s). If there is no match, no output will be printed to the terminal.
For example, say we have the following files (called grep.txt):
Hello, how are you
I am grep
Nice to meet you
The following grep
command will search for all occurences of the word ‘you’:
grep you grep.txt
The result for this is:
Hello, how are you
Nice to meet you
you
is expected to have a different color than the other text to easily identify what was searched for.
But grep
comes with more options which help us achieve more during a search operation. Let’s look at nine of them while applying them to the example above.
Options used with grep
1. -n
(–line-number) – list line numbers
This prints out the matches for the text along with the line numbers. If you look at the result we have above, you’ll notice there are no line numbers, just the matches.
grep you grep.txt -n
Result:
1: Hello, how are you
3: Nice to meet you
2. -c
(–count) – prints the number of lines of matches
grep you grep.txt -c
Result:
2
Note that if there was another ‘you’ on line one, option -c
would still print 2. This is because it is concerned with the number of lines where the matches appear, not the number of matches.
3. -v
(–invert-match) – prints the lines that do not match the specified pattern
grep you grep.txt -v -n
Result:
2. I am grep
Notice that we also used option -n
? Yes, you can apply multiple options in one command.
4. -i
(–ignore-case) – used for case insensitivity
# command 1
grep You grep.txt
# command 2
grep YoU grep.txt -i
Results:
# result 1
# no result
# result 2
Hello, how are you
Nice to meet you
5. -l
(–files-with-matches) – print file names that match a pattern
# command 1
grep you grep.txt -l
# command 2
grep You grep.txt -i -l
Results:
# result 1
grep.txt
# result 2
# all files in the current directory that matches
# the text 'You' case insensitively
#### 6. `-w` (--word-regexp) - print matches of the whole word
By default, grep
matches strings which contain the specified pattern. This means that grep yo grep.txt
will print the same results as grep yo grep.txt
because ‘yo’ can be found in you. Similarly, ‘ou’.
With the option -w
, grep
ensures that the matches are exactly the same pattern as specified. Example:
grep yo grep.txt -w
Result:
No result!
7. -o
(–only-matching) – print only the matched pattern
By default, grep
prints the line where the matched pattern is found. With option -o
, only the matched pattern is printed line by line. Example:
grep yo grep.txt -o
Result:
yo
8. -A
(–after-context) and -B
(–before-context) – print the lines after and before (respectively) the matched pattern
grep grep grep.txt -A 1 -B 1
Result:
Hello, how are you
I am grep
Nice to meet you
This matched pattern is on line 2. -A 1
means one line after the matched line and -B 1
means one line before the matched line.
There’s also a -C
(–context) option which is equal to -A
+ -B
. The value passed to -C
would be used for -A
and -B
.
9. -R
(–dereference-recursive) – recursive search
By default, grep
cannot search directories. If you try doing so, you’ll get an error (“Is a directory”). With option -R
, searching files within directories and subdirectories becomes possible. Example:
grep you .
Result:
# 'you' matches in a folders
# and files starting from the
# current directory
Regular expressions for patterns
grep
also allows basic regular expressions for specifying patterns. Two of them are:
1. ^pattern
– start of a line
This pattern means that the grep
will match the strings whose lines begin with the string specified after ^
. Example:
grep ^I grep.txt -n
Result:
2: I
2. pattern$
– end of a line
In contrast with ^
, $
specifies patterns that will be matched if the line ends with the string before $
. Example:
grep you$ grep.txt
Result:
1: Hello, how are you
3: Nice to meet you
Wrap up
grep
is a powerful tool for searching files in the terminal. Understanding how to use it gives you the ability to easily find files via the terminal.
There are more options attached to this tool. You can find with man grep
.
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
Изначально операционные системы Unix/Linux не имели графического интерфейса, поскольку были ориентированы на серверное применение. Сегодня в этом плане они мало в чём уступают Windows, из-за чего пользователи, использующие эту ОС, редко знают синтаксис и назначение основных команд Linux. Между тем это весьма мощный инструмент, позволяющий быстро выполнять операции, которые с помощью базовых средств ОС выполнить проблематично или невозможно. Сегодня вы познакомитесь с операторами find и grep, являющимися базовыми для файловой системы всех дистрибутивов Linux.
Назначение операторов find и grep
Команда find в Linux является оператором командной строки для работы с файлами в обход существующей иерархии. Она позволяет производить поиск файлов с использованием множества фильтров, а также выполнять некие действия над файлами после их успешного поиска. Среди критериев поиска файлов – практически все доступные атрибуты, от даты создания до разрешения.
Команда grep в Linux также относится к поисковым, но внутри файлов. Буквальный перевод команды – «глобальная печать регулярных выражений», но под печатью здесь понимается вывод результатов работы на устройство по умолчанию, каковым обычно является монитор. Обладая огромным потенциалом, оператор используется достаточно часто и позволяет производить поиск внутри одного или нескольких файлов по заданным фрагментам (шаблонам). Поскольку терминология в Linuxе существенно отличается от таковой в среде Windows, очень многие пользователи испытывают значительные трудности с использованием этих команд. Постараемся устранить этот недостаток.
Синтаксис grep и find
Начнём с оператора find. Синтаксис файловой поисковой команды выглядит так:
find [где искать] [параметры] [-опции] [действия]
Некоторые употребительные параметры:
- -depth : поиск в текущей папке и подкаталогах;
- -version : вывести версию команды;
- -print : показывать полные имена файлов (в Linux они могут быть сколь угодно большими);
- -type f : поиск исключительно файлов;
- -type d – поиск только директорий (папок).
Перечень доступных опций (указываются через дефис):
- name : файловый поиск по имени;
- user : поиск по имени владельца файла;
- perm : по атрибуту «режим доступа»;
- mtime : по времени последнего изменения (редактирования) файла;
- group : по группе;
- atime : по дате последнего открытия файла;
- newer : поиск файла с датой, более новой, чем заданная в шаблоне директивы;
- size : по размеру файла в байтах;
- nouser : поиск файлов, не имеющих введённого атрибута «владелец».
Синтаксис grep:
grep [опции] шаблон [где искать]
Под опциями следует понимать дополнительные уточняющие параметры, например, использование инверсного режима или поиск заданного количество строк.
В шаблоне указывается, что нужно искать, используя непосредственно заданную строку или регулярное выражение.
Возможность использования регулярных выражений позволяет существенно расширить возможности поиска. Указание стандартного вывода может оказаться полезным, если стоит задача отфильтровать ошибки, записанные в логи, или для поиска PID процесса в результатах выполнения команды ps, которые могут быть многостраничными.
Рассмотрим наиболее употребительные параметры grep:
- -b : выводить номер блока перед выдачей результирующей строки;
- -c : необходимо подсчитать число вхождений искомого фрагмента;
- -i : поиск без учёта регистра;
- -n : выдавать на стандартное устройство вывода номер строки, в которой найден искомый фрагмент или шаблон;
- – l : в результате выдачи должны присутствовать только имена файлов с найденным поисковым фрагментом;
- -s : игнорировать вывод ошибок;
- -w : поиск фрагмента, опоясанного с двух сторон пробелами;
- -v : инвертированный поиск, то есть отображение всех строк, не содержащих заданный фрагмент;
- -e : параметр указывает, что далее следует регулярное выражение, имеющее собственный синтаксис;
- -An : вывод искомого фрагмента и предыдущих n строк;
- -Bn : то же, но со строками, идущими после шаблона.
Теперь имеет смысл перейти от теоретической части к практической.3
Примеры использования утилит
Если вы знаете, что такое комбинаторика, то должны представлять истинное количество возможных комбинаций команд поиска. Мы ограничимся только наиболее полезными примерами, которые могут вам пригодиться при работе.
Поиск текста в файлах
Пускай мы имеем права администратора и перед нами поставлена задача отыскать конкретного пользователя в огромном файле паролей. Нам понадобится довольно простая команда с указанием пути размещения файла:
grep NameUser /etc/passwd
Если результат поиска будет положительным, мы получим результирующую строку примерно следующего вида:
NameUser:x:1021:1021: NameUser,,,:/home/User:/bin/bash
Если потребуется осуществить поиск фрагмента текста без учёта регистра символов, команда будет выглядеть так:
grep -i "nameuser" /etc/passwd
В этом случае будет найден и пользователь NameUser, и его «однофамилец» nameuser, а также все другие возможные комбинации.
Вывод нескольких строк
Пускай нам нужно вывести все ошибки из лога оконной оболочки Xorg.log. Задача осложняется тем, что после ошибочной может следовать строка, содержащая ценные сведения. Она решается, если мы заставим команду отображать несколько строк, используя в качестве шаблона строку «РР»:
grep –A5 "РР" /var/log/xorg.0.log
Получим строку, содержащую шаблон и 5 строк после неё.
grep –C3 "РР" /var/log/xorg.0.log
Вывод строки с фрагментом текста и тремя строками до и после.
Использование в grep регулярных выражений
Это один из самых мощных инструментов Linux, существенно расширяющий возможности формирования поискового шаблона. Регулярные выражения имеют свой синтаксис, достаточно сложный. Мы не будем в него углубляться, ограничившись примером использования РВ. Как вы уже знаете, для указания, что далее используется регулярное выражение, используется параметр -e.
Пускай нам в файле messages.2 нужно выловить все строки за сентябрь:
grep "^Sep 09"
Итог будет примерно таким:
Sep 09 01:11:45 gs124 ntpd[2243]: time reset +0.197579 s
Sep 09 01:19:10 gs124 ntpd[2243]: time reset +0.203484 s
Для поиска шаблона, расположенного в конце строки фала, используется символ «$»:
grep "term.$" messages
Результат:
Jun 17 19:01:19 cloneme kernel: Log daemon term.
Sep 11 06:30:54 cloneme kernel: Log daemon term.
А вот пример использования регулярного выражения, позволяющего выполнить поиск строк, содержащих любые цифры, кроме нуля:
grep "[1-9]" /var/log/Xorg.1.log
Использование рекурсивного поиска в grep
Если вы знакомы с термином «рекурсия», то в Linuxе этот приём используется, в частности, для поиска фрагмента в нескольких файлах, расположенных в каталоге и его подкаталогах. О наличии рекурсии укажет опция -r. Пускай нам нужно искать фрагмент «namedomain.org» в файлах, расположенных в подкаталогах папки /etc/apache1:
grep -r "namedomain.org" /etc/apache1/
Результат может быть примерно таким:
/etc/apache1/vhosts.d/ namedomain.org
Если показ имени файла не требуется, используем опцию -h:
grep -h -r "namedomain.org" /etc/apache1/
Поиск слов
Стандартно поиск фрагмента qwe завершится выдачей всех слов, в которых встречается этот фрагмент: kbqwe, qwe123, aafrqwe32. Чтобы ограничить поиск только заданным фрагментом, нужно использовать параметр -w:
grep -w "qwe" где_искать
Поиск двух или нескольких слов
Усложним задачу: нам нужно найти все строки, где встречается два слова. Команда будет такой:
grep -w "word01|word02" где_искать
Количество вхождений строки
Если требуется подсчитать. Сколько раз искомый фрагмент встречается в файле, используем конструкцию с параметром -c:
grep -c "'text» где_искать
Параметр -n поможет узнать, в какой строке встречается искомый шаблон:
grep -n "nuser" /etc/passwd
Инвертированный поиск с помощью grep
Иногда задача поиска с использованием grep по содержимому файлов имеет цель найти не само вхождение, а строки, где этот фрагмент отсутствует. Нам поможет опция –v:
grep -v "txt" где_искать
Вывод имени файла
Пускай вам нужно найти все файлы в указанной директории, содержащие искомый шаблон. Это можно сделать, используя параметр -l. Так, полная команда для вывода файлов, содержащих строку «secondary» в папке /etc будет выглядеть следующим образом:
grep -l "secondary" /etc
Цветной вывод с использованием grep
Выделение другим цветом – отличный способ визуализировать искомое вхождение, существенно снижающий нагрузку на глаза, если операция выполняется часто. Оказывается, grep имеет опцию и для такого вывода результатов поиска:
grep --color "secondary" /etc
Переходим к рассмотрению примеров использования утилиты find в Linux.
Поиск всех файлов
Для вывода списка файлов, расположенных в текущем каталоге, используем команду в следующем формате:
find .
Если необходимо показать полное имя файлов, используем команду
find . -print
Вывод файлов в заданном каталоге
Для поиска файлов в определенной пользователем папке используем команду
find ./etc
А вот как можно найти файлы, содержащие в имени заданный фрагмент, в текущем каталоге:
find . -name "*.gif"
Если поиск нужно осуществить без учёта регистра, команду нужно модифицировать:
Не учитывать регистр при поиске по имени:
find . -iname "*.gif"
Ограничение глубины поиска
Ещё одна достаточно типичная задача – поиск файлов в конкретной папке по заданному имени:
find . –maxdepth01 1 -name "*.html"
Инвертирование шаблона
Мы уже рассматривали аналог команды для поиска строк, не содержащих заданный фрагмент. Точно так же можно поступить и с файлами, не соответствующими заданному шаблону:
find . -not -name "user*"
Поиск по нескольким критериям
Приводим пример командной строки с использованием утилиты find для поиска по двум критериям с использованием оператора not (исключение):
find . -name "user" -not -name "*.html"
В этом случае будут найдены файлы, имя которых включает фрагмент user, но у которых расширение – не html. Вместо оператора исключения можно использовать логическое «И»/»ИЛИ»:
find -name "*.js" -o -name "*.sql"
В этом случае мы получим полный список файлов с обоими расширениями, расположенными в текущей директории.
Поиск в нескольких каталогах
Если нам нужно найти файлы в двух каталогах, просто указываем из через пробел:
find -type f ./test01 ./test02 -name "*.sql"
Поиск скрытых файлов
В Linuxе, как и в Виндовс, существуют скрытые файлы, которые при использовании команды find без специального символа показываться не будут. Этот символ – «тильда», а директива будет иметь следующий вид:
find ~ -name ".*"
Поиск файлов в Linux по разрешениям
Иногда возникает потребность фильтрации каталога по определённой маске прав. Например, если нам нужно найти файлы с атрибутом 0661, используем команду:
find . -perm 0661
Задача фильтрации файлов с атрибутом «только для чтения» решается так:
find /etc/user -perm /u=r
А вот как будет выглядеть поиск исполняемых файлов в каталоге etc:
find /etc -perm /a=x
Поиск файлов по группах/пользователях
Администратору часто приходится сталкиваться с задачей поиска файлов, являющихся собственностью конкретного пользователя и/или группы. Поиск по юзеру:
find . -user slavko
Для групп пользователей используется другой параметр:
find /var -group devs
Поиск по дате последней модификации
Видимый формат даты файла в ОС Linux как раз и относится к дате его модификации (такой же принцип используется и в Windows). Для формирования списка по дате применяется опция mtime. Допустим, нам нужно отыскать файлы, изменённые два месяца назад:
find /home -mtime 60
В числе атрибутов файла есть и дата его последнего открытия (без внесения изменений). Такие файлы выводятся следующей командой:
find /home -atime 60
Можно также задавать промежуток времени. Для поиска файлов, модифицированных в промежутке от четырёх до двух месяцев назад, используем директиву:
find /home -mtime +60 –mtime -120
А вот как найти свежеизменённые файлы (двухчасовой давности):
find /home -cmin 120
Поиск файлов по размеру
Подозреваете, что кто-то использует диск для размещения фильмов? Ищем файлы размером 1.4 ГБ:
find / -size 1400M
Или используем диапазон:
find / -size +1400M -size -2800M
Поиск пустых файлов/каталогов
Да, не удивляйтесь. Задача наведения порядка на носителе характерна не только для ОС Android. В Linux она решается с помощью такой директивы:
find /var -type f -empty
Пример действий с найденными файлами
В Linux команда find рекурсивно может выполнять определённые действия с теми файлами, поиск которых вы ведёте. Для выполнения файловых команд нужно использовать параметр exec. Так, директива для показа информации обо всех файлах с использованием команды ls будет выглядеть так:
find . -exec ls -l {} ;
А вот как просто можно удалить временные файлы с заданной маской в директории /home/temp:
find /tmp -type f -name “*.html” -exec rm -f {} ;
Безусловно, для новичка использование для поиска командной строки с огромным числом опций покажется несколько вычурным способом, но в Linux это в порядке вещей. А как бы вы решали описанные здесь задачи в Windows? То-то же. В этом аспекте Linux явно впереди.