Другое

Как использовать grep для исключения бинарных файлов

Изучите эффективные команды grep для поиска в текстовых файлах, исключая бинарные файлы, такие как JPEG и PNG, чтобы ускорить поиск и повысить производительность.

Как можно использовать grep для поиска конкретной строки в текстовых файлах, исключая бинарные файлы, такие как JPEG и PNG изображения? Сейчас я применяю

bash
grep -ircl "foo=" *

но это медленно, потому что сканируются и бинарные файлы. Я знаю, что grep имеет опции --include и --exclude, но не уверен, какой паттерн использовать, чтобы исключить файлы изображений. Мне нужен вариант, который работает с обычными инструментами вроде grep или find, так как я не могу установить дополнительное ПО. Структура каталогов сложная, поэтому ограничить поиск конкретными папками нельзя, а перемещать проблемные файлы тоже невозможно.

Вы можете использовать флаг -I grep, чтобы полностью игнорировать бинарные файлы, либо комбинировать шаблоны --exclude с подстановочными символами, например *.jpg, *.png и *.gif, чтобы пропустить файлы изображений. Самое эффективное решение для вашей команды grep -ircl "foo=" * — использовать grep -irclI --exclude="*.{jpg,png,gif,jpeg,bmp,tiff}" "foo=" *, которое одновременно игнорирует бинарные файлы и исключает распространённые расширения изображений, значительно улучшая производительность поиска.


Содержание


Почему бинарные файлы замедляют поиск grep

Бинарные файлы содержат не текстовые данные, которые могут заставлять grep обрабатывать их медленно, особенно при рекурсивных поисках. Когда grep сталкивается с бинарными файлами, ему приходится:

  • Читать и интерпретировать бинарное содержимое символ за символом
  • Пытаться сопоставлять шаблоны с произвольными последовательностями байтов
  • Обрабатывать возможные проблемы с кодировкой и специальными символами
  • Обрабатывать большие файлы, которые не содержат полезного текстового контента

Это объясняет, почему ваша текущая команда grep -ircl "foo=" * медленная — она сканирует JPEG и PNG изображения, содержащие бинарные данные, которые не совпадают с вашим поисковым шаблоном, но всё равно требуют времени на обработку.

Примечание: Согласно Unix & Linux Stack Exchange, бинарные файлы могут заставлять grep вести себя непредсказуемо и потреблять чрезмерные ресурсы, поскольку они содержат байты, не представляющие печатные символы.


Использование встроенной обработки бинарных файлов в grep

Самое простое решение — использовать встроенные опции обработки бинарных файлов в grep:

Флаг -I (Рекомендуется)

Флаг -I сообщает grep полностью игнорировать бинарные файлы, что является самым простым подходом:

bash
grep -irclI "foo=" *

Этот флаг эквивалентен --binary-files=without-match и пропускает любые файлы, которые grep определяет как бинарные.

Опция --binary-files

Для большего контроля можно использовать опцию --binary-files:

bash
grep --binary-files=without-match -ircl "foo=" *

Согласно обсуждению на Stack Overflow, эта опция специально предназначена для обработки бинарных файлов, пропуская их полностью, а не пытаясь искать внутри них.


Исключение конкретных типов файлов с помощью --exclude

Чтобы исключить конкретные типы файлов изображений с помощью сопоставления шаблонов, вы можете использовать опцию --exclude с подходящими подстановочными символами:

Базовый синтаксис

bash
grep --exclude="*.jpg" --exclude="*.png" --exclude="*.gif" -ircl "foo=" *

Объединение нескольких расширений

Для более чистого синтаксиса можно объединить несколько расширений в один шаблон:

bash
grep --exclude="*.{jpg,png,gif,jpeg,bmp,tiff}" -ircl "foo=" *

Этот шаблон использует расширение скобок, чтобы сопоставить любой файл, заканчивающийся указанными расширениями.

Полный пример со всеми распространёнными типами изображений

bash
grep --exclude="*.{jpg,jpeg,png,gif,bmp,tiff,webp,ico,svg}" -ircl "foo=" *

Документация Linuxize объясняет, что опция --exclude использует шаблоны glob для указания файлов, которые должны быть пропущены во время поиска. Эти шаблоны поддерживают подстановочные символы, такие как * для любых символов и ? для одного символа.

Важно: Синтаксис расширения скобок *.{jpg,png,gif} может не работать во всех оболочках. Если вы столкнетесь с проблемами, используйте отдельные опции --exclude для каждого типа файлов.


Комбинирование find и grep для сложных исключений

Для более сложных сценариев, когда вам нужен тонкий контроль над тем, какие файлы исключать, вы можете комбинировать find с grep:

Использование find для фильтрации файлов

bash
find . -type f \( ! -name "*.jpg" ! -name "*.png" ! -name "*.gif" \) -print0 | xargs -0 grep -ircl "foo="

Оптимизированная команда find

Согласно ответу на Stack Overflow, вы можете создать более эффективную команду find:

bash
find . -type f \( -name "*.txt" -o -name "*.csv" -o -name "*.xml" \) -print0 | xargs -0 grep -ircl "foo="

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

Альтернативный синтаксис find

bash
find . -type f ! -regex ".*\.\(jpg\|png\|gif\|jpeg\|bmp\|tiff\)$" -print0 | xargs -0 grep -ircl "foo="

Документация Data Science Workbench показывает примеры сложных команд find, которые объединяют несколько критериев исключения с использованием регулярных выражений.


Стратегии оптимизации производительности

Сочетанный подход (наилучшая производительность)

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

bash
grep -irclI --exclude="*.{jpg,png,gif,jpeg,bmp,tiff,webp,ico,svg}" "foo=" *

Эта команда:

  • Использует -I, чтобы пропустить бинарные файлы
  • Исключает распространённые расширения файлов изображений
  • Сохраняет вашу исходную функциональность поиска

Рекурсивный поиск с исключением каталогов

Если у вас есть каталоги, содержащие много бинарных файлов, полностью исключите их:

bash
grep -rI --exclude-dir="images" --exclude-dir="assets" "foo=" *

Использование -F для поиска фиксированной строки

Если вы ищете литеральную строку, а не шаблон регулярного выражения, используйте флаг -F:

bash
grep -irclFI --exclude="*.{jpg,png,gif,jpeg,bmp,tiff}" "foo=" *

Учебник phoenixnap объясняет, что поиск фиксированной строки (-F) может быть быстрее, чем поиск по регулярному выражению для простых шаблонов.


Дополнительные типы бинарных файлов, которые стоит учесть

Помимо JPEG и PNG, возможно, вы захотите исключить другие распространённые типы бинарных файлов:

Распространённые расширения бинарных файлов

bash
# Форматы документов
--exclude="*.{doc,docx,pdf,xls,xlsx,ppt,pptx}"

# Аудиофайлы
--exclude="*.{mp3,mp4,wav,aac,flac,m4a}"

# Видеофайлы
--exclude="*.{avi,mov,wmv,flv,mkv,m4v}"

# Архивы
--exclude="*.{zip,7z,rar,tar,gz,bz2}"

Полный шаблон исключения

bash
grep -irclI --exclude="*.{jpg,jpeg,png,gif,bmp,tiff,webp,ico,svg,doc,docx,pdf,xls,xlsx,ppt,pptx,mp3,mp4,wav,aac,flac,m4a,avi,mov,wmv,flv,mkv,m4v,zip,7z,rar,tar,gz,bz2}" "foo=" *

Статья Baeldung предоставляет дополнительные сведения о выявлении и исключении различных типов бинарных файлов, которые могут замедлять ваши поиски grep.


Заключение

Для эффективного поиска строк с исключением бинарных файлов, таких как JPEG и PNG, у вас есть несколько практических вариантов:

  1. Использовать флаг -I: Самое простое решение — grep -irclI "foo=" *, который автоматически пропускает бинарные файлы
  2. Комбинировать шаблоны --exclude: Используйте grep --exclude="*.{jpg,png,gif,jpeg,bmp,tiff}" -ircl "foo=" * для исключения конкретных типов файлов
  3. Использовать комбинацию find: Для сложных сценариев комбинируйте find с grep, используя find . -type f ! -regex ".*\.\(jpg\|png\|gif\|jpeg\|bmp\|tiff\)$" -print0 | xargs -0 grep -ircl "foo="
  4. Оптимизировать производительность: Комбинируйте подходы с grep -irclI --exclude="*.{jpg,png,gif,jpeg,bmp,tiff}" "foo=" * для лучших результатов

Для вашего конкретного случая начните с комбинированного подхода, использующего как -I, так и шаблоны --exclude — это даст вам лучшую производительность и при этом будет легко поддерживать и изменять по мере необходимости.


Источники

  1. Stack Overflow - How to suppress binary file matching results in grep
  2. Stack Overflow - Use grep --exclude/–include syntax to not grep through certain files
  3. Unix & Linux Stack Exchange - Why doesn’t grep ignore binary files by default?
  4. Data Science Workbench - Grep Ignore Binary Files
  5. phoenixnap - How to Exclude Using grep
  6. Baeldung on Linux - Using grep While Excluding Binary Files
  7. Linuxize - How to Exclude in Grep
  8. explainshell.com - grep command with exclude patterns
Авторы
Проверено модерацией
Модерация