J'utilise find
et j'obtiens une liste des fichiers que je veux grep
. Comment diriger cette liste vers grep
?
Eh bien, le cas générique qui fonctionne avec n'importe quelle commande qui écrit dans stdout est d'utiliser xargs
, qui vous permettra d'attacher n'importe quel nombre d'arguments de ligne de commande à la fin d'une commande:
$ find … | xargs grep 'search'
Ou pour incorporer la commande dans votre ligne grep
avec des backticks ou $()
, qui exécutera la commande et remplacera 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 find
, la possibilité d'exécuter un programme sur les arguments donnés est intégrée:
$ find … -exec grep 'search' {} \;
Tout entre -exec
Et ;
Est la commande à exécuter; {}
Est remplacé par le nom de fichier trouvé par find
. Cela exécutera un grep
distinct pour chaque fichier; comme grep
peut prendre plusieurs noms de fichiers et les rechercher tous, vous pouvez changer le ;
en +
pour dire à find de passer tous les noms de fichiers correspondants à grep
à une fois que:
$ find … -exec grep 'search' {} \+
Certaines versions de grep
(par exemple sur Linux non intégré ou BSD ou Mac OS X) ont un -r
option pour effectuer une recherche récursive. Sur OpenBSD, utilisez -R
(et il n'y a pas de --exclude
comme dans l'exemple ci-dessous). Cela couvre les combinaisons simples de find
avec grep
.
Si votre implémentation n'a pas le -R
flag, ou si vous voulez des critères de correspondance de fichiers plus sophistiqués, vous pouvez utiliser le -exec
primaire de find
pour le faire exécuter grep
. Quelques anciennes implémentations find
ne prennent pas en charge -exec
… +
; sur ces systèmes, utilisez un ;
à la place du +
(cela appellera grep
une fois par fichier, donc ce sera plus lent, mais sinon le résultat sera le même). Noter la /dev/null
astuce pour que grep
affiche le nom du fichier même s'il se trouve être appelé sur un seul fichier (GNU grep et FreeBSD/NetBSD/OSX grep ont un -H
option pour obtenir le même effet).
find . -type f -name '*.o' -Prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .