Поиск и фильтрация в Linux
Практическое руководство по find, grep, конвейерам, перенаправлениям, sort, head, tail, xargs и awk для поиска файлов, обработки логов и диагностики Linux.
Содержание статьи
- Зачем нужны поиск и фильтрация
- Конвейеры и перенаправления
- Поиск текста с grep
- Регулярные выражения на практике
- Поиск файлов через find
- Размер, время и права
- Обработка найденных файлов
- Сортировка и ограничение вывода
- Подсчёт через wc
- Когда нужен awk
- Поиск в логах: практические конвейеры
- Безопасный алгоритм поиска
- Частые ошибки
- Забыть кавычки вокруг шаблона
- Искать от корня без необходимости
- Перепутать `>` и `>>`
- Считать `grep` ошибкой, если совпадений нет
- Применять `xargs` к непроверенному списку
- Итоговая шпаргалка
- Что дальше
Зачем нужны поиск и фильтрация
В 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 скрывает сообщения об отказе в доступе. Используйте его осознанно: ошибки исчезают из вывода и могут быть важны при диагностике.
Безопасный алгоритм поиска
Для сложной задачи действуйте поэтапно:
- Начните с небольшого каталога или ограничьте путь.
- Сначала выведите список результатов без изменений.
- Проверьте количество и несколько элементов вручную.
- Добавьте фильтр по типу, имени, времени или размеру.
- Соединяйте команды конвейером только после проверки каждой части.
- Для действий через
-execсначала используйтеlsилиprintf. - Только затем запускайте изменение, перенос или удаление.
Например, вместо опасного удаления сразу:
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 хороший поиск — это не только умение быстро найти нужную строку, но и привычка не менять данные до проверки результата.