Загружаемся
← Все статьи
INFRASTRUCTURE

Поиск и фильтрация в Linux

Практическое руководство по find, grep, конвейерам, перенаправлениям, sort, head, tail, xargs и awk для поиска файлов, обработки логов и диагностики Linux.

Содержание статьи
  1. Зачем нужны поиск и фильтрация
  2. Конвейеры и перенаправления
  3. Поиск текста с grep
  4. Регулярные выражения на практике
  5. Поиск файлов через find
  6. Размер, время и права
  7. Обработка найденных файлов
  8. Сортировка и ограничение вывода
  9. Подсчёт через wc
  10. Когда нужен awk
  11. Поиск в логах: практические конвейеры
  12. Безопасный алгоритм поиска
  13. Частые ошибки
  14. Забыть кавычки вокруг шаблона
  15. Искать от корня без необходимости
  16. Перепутать `>` и `>>`
  17. Считать `grep` ошибкой, если совпадений нет
  18. Применять `xargs` к непроверенному списку
  19. Итоговая шпаргалка
  20. Что дальше

Зачем нужны поиск и фильтрация

В Linux почти любую задачу приходится начинать с ответа на вопрос: где находится нужный файл, что в нём записано и какие строки действительно важны. Для этого используются find, grep, конвейеры, перенаправления и небольшие текстовые инструменты.

Эти команды особенно полезны администратору: с их помощью можно найти большие файлы, отобрать ошибки из лога, проверить недавно изменённые конфигурации и быстро обработать результат другой команды.

В статье будем работать в безопасном учебном каталоге:

mkdir -p ~/linux-search-lab/logs ~/linux-search-lab/config
cd ~/linux-search-lab
printf 'INFO service started\nWARN connection slow\nERROR database unavailable\nINFO retry started\n' > logs/app.log
printf 'port=8080\nenabled=true\n# temporary option\n' > config/app.conf
printf 'server-1\nserver-2\nserver-10\n' > servers.txt

Конвейеры и перенаправления

Команда | передаёт стандартный вывод одной команды на стандартный ввод другой:

cat logs/app.log | grep ERROR

В простых случаях cat не нужен — файл можно передать grep напрямую:

grep ERROR logs/app.log

Результат можно записать в файл через >:

grep ERROR logs/app.log > errors.txt

Оператор > перезаписывает файл. >> добавляет вывод в конец:

grep WARN logs/app.log >> errors.txt

Ошибки обычно идут в отдельный поток stderr. Объединить обычный вывод и ошибки:

some-command > result.txt 2>&1

В Bash и совместимых оболочках более короткая запись выглядит так:

some-command &> result.txt

Будьте внимательны с перенаправлением: команда > file очищает файл ещё до запуска самой команды.

Поиск текста с grep

grep ищет строки, соответствующие шаблону:

grep 'ERROR' logs/app.log

Полезные опции:

  • -i — игнорировать регистр;
  • -n — показать номера строк;
  • -v — вывести строки, которые не соответствуют шаблону;
  • -w — искать отдельное слово;
  • -F — воспринимать шаблон как обычный текст;
  • -E — включить расширенные регулярные выражения;
  • -r или -R — искать в каталогах рекурсивно;
  • -l — вывести только имена файлов с совпадениями;
  • -c — посчитать количество совпавших строк;
  • -A N и -B N — показать строки после или до совпадения.

Примеры:

grep -n 'ERROR' logs/app.log
grep -i 'warning' logs/app.log
grep -v '^#' config/app.conf
grep -rni 'database' .
grep -rl '8080' config/

Символ ^ обозначает начало строки, $ — конец строки. Поэтому команда:

grep -n '^#' config/app.conf

найдёт комментарии, а:

grep -n 'true$' config/app.conf

— строки, заканчивающиеся словом true.

Если искомая строка содержит символы регулярных выражений, используйте -F:

grep -F 'port=8080' config/app.conf

Для поиска нескольких вариантов удобно использовать -E:

grep -En 'ERROR|WARN' logs/app.log

Регулярные выражения на практике

Расширенные регулярные выражения позволяют описывать группы вариантов:

grep -En '^(ERROR|WARN)' logs/app.log
grep -En 'server-[0-9]+' servers.txt

Квадратные скобки задают набор символов, а + означает «один или больше» при использовании grep -E.

Полезные конструкции:

  • . — любой один символ;
  • [0-9] — одна цифра;
  • [[:digit:]] — цифра в POSIX-записи;
  • * — ноль или больше повторений;
  • + — одно или больше повторений в расширенном режиме;
  • ? — ноль или одно повторение в расширенном режиме;
  • | — один вариант или другой;
  • () — группа выражений;
  • ^ — начало строки;
  • $ — конец строки.

Начинайте с обычного текста и добавляйте регулярные выражения только при необходимости. Сложный шаблон труднее проверить и легко сделать слишком широким.

Поиск файлов через find

find обходит дерево каталогов и выбирает объекты по условиям:

find . -type f

Эта команда найдёт все обычные файлы начиная с текущего каталога. Другие типы:

  • -type d — каталоги;
  • -type l — символические ссылки.

Поиск по имени:

find . -type f -name '*.log'
find . -type f -iname 'readme*'

-name учитывает регистр, -iname — нет. Шаблон обязательно заключайте в кавычки, чтобы оболочка не раскрыла * до запуска find.

Ограничить глубину поиска:

find . -maxdepth 2 -type f
find . -mindepth 2 -type f

Искать вне конкретного каталога:

find . -path './.git' -prune -o -type f -print

Это полезно для проектов, где не нужно обходить .git, node_modules или каталог сборки.

Размер, время и права

Найти файлы больше 100 мегабайт:

find /var/log -type f -size +100M -print

Найти маленькие файлы меньше 10 килобайт:

find . -type f -size -10k -print

Найти файлы, изменённые за последние сутки:

find . -type f -mtime -1 -print

Найти файлы, изменённые более семи дней назад:

find . -type f -mtime +7 -print

Для более точного интервала используйте -mmin:

find /var/log -type f -mmin -30 -print

Поиск по владельцу и правам:

find . -type f -user "$USER"
find . -type f -perm 0777 -print
find . -type f -perm -o=r -print

Условие -perm -o=r означает, что право чтения для остальных пользователей установлено. При анализе чувствительных данных полезнее искать слишком открытые файлы и затем отдельно проверять каждый результат.

Обработка найденных файлов

Показать размер каждого найденного файла:

find . -type f -name '*.log' -exec du -h {} \;

В конструкции -exec пара {} заменяется текущим найденным путём, а \; завершает команду. Экранирование нужно, чтобы точка с запятой не была обработана оболочкой раньше find.

Выполнить действие для каждого файла:

find . -type f -name '*.tmp' -exec ls -lh {} \;

Для групповой обработки используется + вместо ;:

find . -type f -name '*.log' -exec wc -l {} +

В этом случае find передаст несколько файлов одной команде, что обычно быстрее.

Не добавляйте -delete без предварительной проверки. Сначала выполните поиск с -print:

find . -type f -name '*.tmp' -print

Только убедившись, что список правильный, можно рассматривать удаление. Для важных данных сначала сделайте резервную копию.

Сортировка и ограничение вывода

sort сортирует строки:

sort servers.txt
sort -r servers.txt
sort -n numbers.txt

Опция -r меняет порядок на обратный, -n включает числовую сортировку. Для вывода без повторов используйте sort -u:

grep -oE 'server-[0-9]+' input.txt | sort -u

head показывает начало вывода:

head -n 5 logs/app.log

tail — конец:

tail -n 5 logs/app.log

Следить за появлением новых строк в логе:

tail -f logs/app.log

Остановить режим наблюдения можно через Ctrl-c. В production-логах часто используют tail -F, который лучше переживает замену файла при ротации.

Подсчёт через wc

wc считает строки, слова и байты:

wc logs/app.log
wc -l logs/app.log
wc -w logs/app.log
wc -c logs/app.log

Подсчитать ошибки:

grep -c 'ERROR' logs/app.log

Подсчитать количество файлов:

find . -type f | wc -l

Если имена файлов могут содержать переводы строк, такой подсчёт требует осторожности. Для обычных учебных и проектных каталогов он подходит, но в скриптах с произвольными именами лучше использовать нулевой разделитель и соответствующие опции инструментов.

Когда нужен awk

awk обрабатывает текст построчно и разбивает его на поля. Например, вывести первый столбец:

printf 'api 8080\nweb 3000\n' | awk '{print $1}'

По умолчанию поля разделяются пробелами. Вывести строки, где второй столбец больше 3000:

printf 'api 8080\nweb 3000\nadmin 3001\n' | awk '$2 > 3000 {print $1, $2}'

Посчитать сумму числового столбца:

printf 'api 8080\nweb 3000\nadmin 3001\n' | awk '{sum += $2} END {print sum}'

Для CSV и других форматов с разделителем укажите -F:

awk -F: '{print $1}' /etc/passwd

awk мощнее, чем требуется для простого поиска. Используйте его, когда нужно не просто выбрать строки, а извлечь поля или выполнить вычисление.

Поиск в логах: практические конвейеры

Найти ошибки и показать последние десять:

grep -i 'error' /var/log/app.log | tail -n 10

Посчитать ошибки по кодам или словам:

grep -oE 'ERROR|WARN' /var/log/app.log | sort | uniq -c | sort -nr

uniq -c считает только соседние одинаковые строки, поэтому перед ним обычно нужен sort.

Показать ошибку вместе с двумя строками контекста:

grep -n -B 2 -A 2 'ERROR' /var/log/app.log

Найти недавно изменённые конфигурации:

find /etc -type f -mmin -60 -readable -print 2>/dev/null

Перенаправление 2>/dev/null скрывает сообщения об отказе в доступе. Используйте его осознанно: ошибки исчезают из вывода и могут быть важны при диагностике.

Безопасный алгоритм поиска

Для сложной задачи действуйте поэтапно:

  1. Начните с небольшого каталога или ограничьте путь.
  2. Сначала выведите список результатов без изменений.
  3. Проверьте количество и несколько элементов вручную.
  4. Добавьте фильтр по типу, имени, времени или размеру.
  5. Соединяйте команды конвейером только после проверки каждой части.
  6. Для действий через -exec сначала используйте ls или printf.
  7. Только затем запускайте изменение, перенос или удаление.

Например, вместо опасного удаления сразу:

find /tmp -type f -name '*.cache' -delete

сначала выполните:

find /tmp -type f -name '*.cache' -print

и проверьте, что путь и шаблон соответствуют задаче.

Частые ошибки

Забыть кавычки вокруг шаблона

Команда find . -name *.log может быть обработана оболочкой неожиданным образом. Пишите find . -name '*.log'.

Искать от корня без необходимости

find / может долго обходить систему и выдавать много ошибок доступа. Ограничивайте каталог и скрывайте ошибки только если это действительно нужно.

Перепутать > и >>

> перезаписывает файл, а >> добавляет данные. Для важных результатов проверьте команду до запуска.

Считать grep ошибкой, если совпадений нет

grep возвращает код 1, когда совпадений нет. Это нормальное поведение, но в скриптах нужно учитывать его отдельно от настоящей ошибки выполнения.

Применять xargs к непроверенному списку

Имена с пробелами и специальными символами могут обрабатываться неправильно. Если используете find, часто безопаснее начать с -exec. Для сложных случаев изучите нулевой разделитель: find ... -print0 | xargs -0 ....

Итоговая шпаргалка

Задача Команда
Найти текст grep 'текст' файл
Поиск без учёта регистра grep -i 'текст' файл
Показать номера строк grep -n 'текст' файл
Искать рекурсивно grep -r 'текст' каталог
Найти файлы по имени find . -type f -name '*.log'
Найти каталоги find . -type d -name 'cache'
Файлы за последние сутки find . -type f -mtime -1
Файлы больше 100 MB find . -type f -size +100M
Последние строки tail -n 20 файл
Следить за логом tail -F файл
Первые строки head -n 20 файл
Посчитать строки wc -l файл
Отсортировать и убрать повторы sort -u файл
Выполнить команду для результатов find ... -exec команда {} \;
Выбрать поле awk '{print $1}' файл
Передать вывод дальше `команда1

Что дальше

Поиск и фильтрация становятся особенно полезными при диагностике работающих процессов и сервисов. Следующая статья серии — «Процессы в Linux: ps, top, kill и управление задачами».

Перед выполнением команд на production-системе проверяйте путь, шаблон и список результатов. В Linux хороший поиск — это не только умение быстро найти нужную строку, но и привычка не менять данные до проверки результата.

Материал подготовил Злой админ