Comment passer une liste de fichiers à grep


98

J'utilise findet je reçois une liste de fichiers que je veux grepparcourir. Comment puis-je diriger cette liste vers grep?

Réponses:


116

Eh bien, le cas générique qui fonctionne avec n'importe quelle commande qui écrit sur stdout est à utiliser xargs, ce qui vous permettra d'attacher un nombre quelconque d'arguments de ligne de commande à la fin d'une commande:

$ find … | xargs grep 'search'

Ou pour incorporer la commande dans votre grepligne avec des backticks ou $(), qui exécutera la commande et substituera sa sortie:

$ grep 'search' $(find …)

Notez que ces commandes ne fonctionnent pas si les noms de fichiers contiennent des espaces, ou certains autres «caractères étranges» ( \'"pour xargs, \[*?pour $(find …)).


Cependant, dans le cas spécifique de findla capacité à exécuter un programme sur les arguments donnés, cela est intégré:

$ find … -exec grep 'search' {} \;

Tout entre -execet ;est la commande à exécuter; {}est remplacé par le nom de fichier trouvé par find. Cela va exécuter un grepfichier séparé pour chaque fichier; car greppeut prendre plusieurs noms de fichiers et les rechercher tous, vous pouvez changer le mot ;to +pour indiquer find afin de transmettre tous les noms de fichiers correspondants grepà la fois:

$ find … -exec grep 'search' {} \+

1
Il convient de noter que les deux premiers formulaires ne fonctionnent pas avec les noms de fichiers contenant des espaces.
enzotib

1
Je préfère find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED. Bien que -exec +très efficace, il n’existe pas sur toutes les versions de find.
Arcege

Malheureusement, je ne peux pas vérifier correctement 3 fois.
Arcabard

3
Je suggère d'utiliser le -exec, plutôt que le xargs. Si vous utilisez -execin find, il ne créera qu'un seul shell à grep pour le contenu. Si vous utilisez le xargs, cela créera deux coquilles: une pour le findet l'autre pour le xargs.

2
expérimentalement, je trouve que la $ find … -exec grep 'search' {} \+forme est beaucoup plus rapide.
Gogoud

9

Certaines versions de grep(par exemple, sur Linux non intégré, BSD ou Mac OS X) ont une -roption permettant d'effectuer une recherche récursive. Sous OpenBSD, utilisez -R(et il n'y en a pas --excludecomme dans l'exemple ci-dessous). Cela couvre des combinaisons simples de findavec grep.

Si votre implémentation ne possède pas l' -Rindicateur ou si vous souhaitez des critères de correspondance de fichiers plus élaborés, vous pouvez utiliser le -execprincipal de findpour l'exécuter grep. Quelques findimplémentations plus anciennes ne supportent pas -exec+; sur ces systèmes, utilisez a ;au lieu de la +(ceci appelle grepune fois par fichier, donc ce sera plus lent, mais sinon le résultat sera le même). Notez l' /dev/nullastuce pour que greple nom de fichier soit affiché même s'il est appelé sur un seul fichier (GNU grep et FreeBSD / NetBSD / OSX grep ont la -Hpossibilité d'obtenir le même effet).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .

2
GNU grepa l' -Hoption de toujours imprimer le nom de fichier.
enzotib
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.