Изначально операционные системы 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 явно впереди.