Изначально операционные системы Unix/Linux не имели графического интерфейса, поскольку были ориентированы на серверное применение. Сегодня в этом плане они мало в чём уступают Windows, из-за чего пользователи, использующие эту ОС, редко знают синтаксис и назначение основных команд Linux. Между тем это весьма мощный инструмент, позволяющий быстро выполнять операции, которые с помощью базовых средств ОС выполнить проблематично или невозможно. Сегодня вы познакомитесь с операторами find и grep, являющимися базовыми для файловой системы всех дистрибутивов Linux.
Команда find в Linux является оператором командной строки для работы с файлами в обход существующей иерархии. Она позволяет производить поиск файлов с использованием множества фильтров, а также выполнять некие действия над файлами после их успешного поиска. Среди критериев поиска файлов – практически все доступные атрибуты, от даты создания до разрешения.
Команда grep в Linux также относится к поисковым, но внутри файлов. Буквальный перевод команды – «глобальная печать регулярных выражений», но под печатью здесь понимается вывод результатов работы на устройство по умолчанию, каковым обычно является монитор. Обладая огромным потенциалом, оператор используется достаточно часто и позволяет производить поиск внутри одного или нескольких файлов по заданным фрагментам (шаблонам). Поскольку терминология в Linuxе существенно отличается от таковой в среде Windows, очень многие пользователи испытывают значительные трудности с использованием этих команд. Постараемся устранить этот недостаток.
Начнём с оператора find. Синтаксис файловой поисковой команды выглядит так:
find [где искать] [параметры] [-опции] [действия]
Некоторые употребительные параметры:
Перечень доступных опций (указываются через дефис):
Синтаксис grep:
grep [опции] шаблон [где искать]
Под опциями следует понимать дополнительные уточняющие параметры, например, использование инверсного режима или поиск заданного количество строк.
В шаблоне указывается, что нужно искать, используя непосредственно заданную строку или регулярное выражение.
Возможность использования регулярных выражений позволяет существенно расширить возможности поиска. Указание стандартного вывода может оказаться полезным, если стоит задача отфильтровать ошибки, записанные в логи, или для поиска PID процесса в результатах выполнения команды ps, которые могут быть многостраничными.
Рассмотрим наиболее употребительные параметры grep:
Теперь имеет смысл перейти от теоретической части к практической.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
Вывод строки с фрагментом текста и тремя строками до и после.
Это один из самых мощных инструментов 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
Если вы знакомы с термином «рекурсия», то в 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 по содержимому файлов имеет цель найти не само вхождение, а строки, где этот фрагмент отсутствует. Нам поможет опция –v:
grep -v "txt" где_искать
Пускай вам нужно найти все файлы в указанной директории, содержащие искомый шаблон. Это можно сделать, используя параметр -l. Так, полная команда для вывода файлов, содержащих строку «secondary» в папке /etc будет выглядеть следующим образом:
grep -l "secondary" /etc
Выделение другим цветом – отличный способ визуализировать искомое вхождение, существенно снижающий нагрузку на глаза, если операция выполняется часто. Оказывается, 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 ".*"
Иногда возникает потребность фильтрации каталога по определённой маске прав. Например, если нам нужно найти файлы с атрибутом 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 явно впереди.