Unix 'grep' pour une chaîne dans tous les fichiers gzip dans tous les sous-répertoires

8

Comment puis-je rechercher une chaîne de manière récursive dans tous les .gzfichiers de tous les répertoires et sous-répertoires?

Peter Mortensen
la source

Réponses:

13

@Steve Weet est presque là. L'utilisation de / dev / null comme argument supplémentaire est une bonne façon de forcer le nom du fichier à être affiché (je m'en souviendrai, merci Steve) mais il exécute toujours l'exec pour chaque fichier trouvé - une énorme surcharge.

Vous souhaitez exécuter zgrep le plus de fois possible, en tirant le meilleur parti de chaque exécution:

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

xargsfournira autant d'arguments (noms de fichiers) que possible à zgrep, et l'exécutera de manière répétée jusqu'à ce qu'il ait utilisé tous les fichiers fournis par la findcommande. L'utilisation des options -print0et lui -0permet de fonctionner s'il y a des espaces dans l'un des noms de fichier ou de répertoire.

Sur Mac OS X, vous pouvez obtenir le même effet sans xargs:

find . -iname '*.gz' -exec zgrep PATTERN {} +
Stephen P
la source
+1 C'est vraiment sympa. Je n'avais pas réalisé que les xargs passaient plus d'un argument. Une grande partie de ma ligne de commande * nix-fu a 20 ans et je ne pense pas que xargs l'a fait il y a 20 ans.
Steve Weet
Il s'avère que find sur os / x se comporte de la même manière que xargs
Steve Weet
1
Voir mon commentaire à la réponse de Steve Weet concernant la terminaison «+» à -exec.
Daniel Andersson
Utilisez -Hpour toujours afficher le nom du fichier avec la ligne correspondante, au moins dans GNU grep.
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.

Donc quelque chose comme

find . -iname "*.gz" -exec zgrep PATTERN {} \
aioobe
la source
-Exec générera une nouvelle instance de zgrep pour chaque fichier qu'il itère afin de vous empêcher de voir le nom du fichier. Il serait préférable d'utiliser zgrep -rpour parcourir un arbre ou si le -r ne fonctionne pas, canalisez la sortie de la recherche viaxargs zgrep
Noufal Ibrahim
Je monte /bin/zgrep: -r: option not supportedsur mon système ubuntu nouvellement installé.
aioobe
Vous pouvez alors utiliser à la xargsplace.
Noufal Ibrahim
Voir mon commentaire à la réponse de Steve Weet concernant la terminaison «+» à -exec.
Daniel Andersson
1

@aioobe est presque là. La commande fera le travail mais ne vous dira pas le nom du fichier

Les informations suivantes devraient également vous indiquer le nom du fichier:

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

L'ajout de /dev/nullfera en sorte que zgrep voit deux noms de fichiers afin qu'il vous montre le nom du fichier s'il trouve la chaîne

ÉDITER

Des recherches plus approfondies révèlent que pour ma machine (OS / X), l' -execargument à rechercher ajoutera autant de noms de fichiers que possible (similaire à la façon dont xargsse comporte).

Steve Weet
la source
C'est assez cool, je ne savais pas cela sur OSX -exec- je suis tout au sujet de la portabilité, donc je ne l'utiliserais pas dans un script, mais parfait pour l'invite de commande.
Pour les autres versions de find, utilisez '+' au lieu de '\;' pour terminer l'instruction exec fera la même chose que OSX, par les histoires de ce fil, par défaut. Voir l'entrée manuelle pour '-exec command {} +'. Ce n'est pas le cas de toutes les versions de find, mais de la plupart des versions modernes (par exemple dans les distributions basées sur Debian).
Daniel Andersson
Utilisez -Hpour toujours afficher le nom du fichier avec la ligne correspondante, au moins dans GNU grep, au lieu du /dev/nullhack.
Daniel Andersson
0

Ce qui suit un régal dans zsh

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

Il peut aussi travailler bash, kshetc ...

Johnsyweb
la source