Unix 'grep' para una cadena dentro de todos los archivos gzip en todos los subdirectorios

8

¿Cómo busco una cadena recursivamente a través de todos los .gzarchivos en todos los directorios y subdirectorios?

Peter Mortensen
fuente

Respuestas:

13

@ Steve Weet ya casi está allí. El uso de / dev / null como argumento adicional es una buena manera de obligar a que se muestre el nombre de archivo (lo recordaré, gracias Steve), pero aún ejecuta el archivo ejecutable para cada archivo encontrado: una gran sobrecarga.

Desea ejecutar zgrep tan pocas veces como sea posible, aprovechando al máximo cada ejecución:

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

xargssuministrará tantos args (nombres de archivo) como sea posible para zgrep, y lo ejecutará repetidamente hasta que haya utilizado todos los archivos proporcionados por el findcomando. El uso de las opciones -print0y le -0permite funcionar si hay espacios en alguno de los nombres de archivo o directorio.

En Mac OS X, puede lograr el mismo efecto sin xargs:

find . -iname '*.gz' -exec zgrep PATTERN {} +
Stephen P
fuente
+1 Eso es muy bueno. No me había dado cuenta de que los xargs pasaban más de un argumento. Gran parte de mi línea de comando * nix-fu tiene 20 años y no creo que xargs lo haya hecho hace 20 años.
Steve Weet
Resulta que find en os / x se comporta de la misma manera que xargs
Steve Weet
1
Vea mi comentario a la respuesta de Steve Weet con respecto al '+' que termina en -exec.
Daniel Andersson
Use -Hpara mostrar siempre el nombre del archivo con la línea correspondiente, en GNU grep al menos.
Daniel Andersson
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.

Entonces algo como

find . -iname "*.gz" -exec zgrep PATTERN {} \
aioobe
fuente
-Exec generará una nueva instancia de zgrep para cada archivo que itera evitando que vea el nombre del archivo. Sería mejor usarlo zgrep -rpara atravesar un árbol o si -r no funciona, xargs zgrep
canalice
Me conecto /bin/zgrep: -r: option not supporteda mi sistema ubuntu recién instalado.
aioobe
Puedes usar xargsen su lugar entonces.
Noufal Ibrahim
Vea mi comentario a la respuesta de Steve Weet con respecto al '+' que termina en -exec.
Daniel Andersson
1

@aioobe ya casi está allí. El comando hará el trabajo pero no le dirá el nombre del archivo

Lo siguiente también debería decirle el nombre del archivo:

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

La adición de /dev/nullasegurará que zgrep vea dos nombres de archivo, por lo que le mostrará el nombre del archivo si encuentra la cadena

EDITAR

Investigaciones posteriores revelan que para mi máquina (OS / X) el -execargumento para encontrar agregará tantos nombres de archivos como sea posible (similar al xargscomportamiento).

Steve Weet
fuente
Eso es bastante bueno, no sabía eso sobre el OSX -exec: soy todo acerca de la portabilidad, así que no lo usaría en un script, pero es genial para el símbolo del sistema.
Para otras versiones de find, use '+' en lugar de '\;' Para finalizar, la declaración ejecutiva hará lo mismo que OSX, según las historias de este hilo, lo hace de forma predeterminada. Consulte la entrada manual para '-exec command {} +'. No es cierto para todas las versiones de find, pero la mayoría de las modernas (por ejemplo, en distribuciones basadas en Debian).
Daniel Andersson
Use -Hpara mostrar siempre el nombre del archivo con la línea correspondiente, al menos en GNU grep, en lugar del /dev/nullhack.
Daniel Andersson
0

Lo siguiente funciona una delicia en zsh

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

También puede trabajar en bash, ksh, etc ...

Johnsyweb
fuente