Unix 'grep' для строки во всех файлах gzip во всех подкаталогах

8

Как я могу grep для строки рекурсивно через все .gzфайлы во всех каталогах и подкаталогах?

Питер Мортенсен
источник

Ответы:

13

@ Steve Weet почти там. Использование / dev / null в качестве дополнительного аргумента является хорошим способом заставить имя файла отображаться (я буду помнить это, спасибо Стиву), но он все равно запускает exec для каждого найденного файла - огромные накладные расходы.

Вы хотите запускать zgrep как можно меньше раз, получая максимальную отдачу от каждого выполнения:

find . -iname '*.gz' -print0 | xargs -0 zgrep PATTERN

xargsпредоставит zgrep столько аргументов (имен файлов), сколько возможно, и будет выполнять его несколько раз, пока не будут использованы все файлы, предоставленные findкомандой. Использование параметров -print0и -0позволяет работать, если в именах файлов или каталогов есть пробелы.

В Mac OS X вы можете добиться того же эффекта без xargs:

find . -iname '*.gz' -exec zgrep PATTERN {} +
Стивен П
источник
+1 Это действительно мило. Я не понял, что xargs передал более одного аргумента. Большей части моей * nix командной строки-фу 20 лет, и я не думаю, что xargs сделал это 20 лет назад.
Стив Уит
Оказывается, что find на os / x ведет себя так же, как xargs
Стив Уит
1
Смотрите мой комментарий к ответу Стива Вита относительно окончания символа «+» на -exec.
Даниэль Андерссон
Используйте, -Hчтобы всегда показывать имя файла с соответствующей строкой, по крайней мере, в GNU grep.
Даниэль Андерссон
1
$ zgrep --help
Usage: /bin/zgrep [OPTION]... [-e] PATTERN [FILE]...
Look for instances of PATTERN in the input FILEs, using their
uncompressed contents if they are compressed.

Так что-то вроде

find . -iname "*.gz" -exec zgrep PATTERN {} \
aioobe
источник
-Exec будет порождать новый экземпляр zgrep для каждого итерируемого файла, не давая вам увидеть имя файла. Было бы лучше использовать, zgrep -rчтобы пройти по дереву, или, если -r не работает, перенаправить вывод поиска черезxargs zgrep
Noufal Ibrahim
Я /bin/zgrep: -r: option not supportedвхожу в мою недавно установленную систему Ubuntu.
aioobe
Вы можете использовать xargsвместо этого тогда.
Нуфал Ибрагим
Смотрите мой комментарий к ответу Стива Вита относительно окончания символа «+» на -exec.
Даниэль Андерссон
1

@aioobe почти там. Команда выполнит работу, но не сообщит вам имя файла

Следующее должно также сказать вам имя файла:

find . -iname "*.gz" -exec zgrep PATTERN {} /dev/null \;

Добавление /dev/nullгарантирует, что zgrep видит два имени файла, поэтому он покажет вам имя файла, если найдет строку

РЕДАКТИРОВАТЬ

Дальнейшие исследования показывают, что для моей машины (OS / X) -execаргумент для поиска добавит столько имен файлов, сколько возможно (аналогично тому, как xargsведет себя).

Стив Уит
источник
Это довольно круто, я не знал об OSX -exec- я все о переносимости, поэтому я бы не использовал его в скрипте, но отлично подходит для командной строки.
Для других версий поиска используйте «+» вместо «\;» для завершения оператор exec будет делать то же самое, что OSX, по рассказам в этой теме, по умолчанию. Смотрите ручную запись для '-exec command {} +'. Это относится не ко всем версиям find, но к большинству современных (например, в дистрибутивах на основе Debian).
Даниэль Андерссон
Используйте, -Hчтобы всегда показывать имя файла с соответствующей строкой, по крайней мере, в GNU grep, вместо /dev/nullвзлома.
Даниэль Андерссон
0

Следующие работы угощение в zsh

for archive in **/*.gz; do
    echo "[${archive}] "
    gzip -dc ${archive} | grep -n "String"
done

Это может также работать bash, kshи т. Д.

Johnsyweb
источник