Comment puis-je grep les résultats de FIND en utilisant -EXEC et toujours sortir dans un fichier?

64

Mieux vaut expliquer sur des exemples.

Je peux:

find . -name "*.py" -type f > output.txt

Mais comment puis-je stocker la sortie dans le même fichier pour:

find . -name "*.py" -type f -exec grep "something" {} \

Je ne peux pas faire

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
Bakytn
la source

Réponses:

106

Si je vous comprends bien, voici ce que vous voulez faire:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Findtous les fichiers avec extension py, grepuniquement les lignes qui contiennent somethinget sauvegardent les lignes dans output.txt. Si le fichier contient quelque chose, il sera remplacé.

Edit: Utiliser -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

J'incorpore le commentaire de Chris Downs ici. La commande ci-dessus entraînera l' grepexécution autant de fois que d' findoccurrences de la recherche. Toutefois, si vous remplacez le ;par un +, grepest appelé avec la sortie findconcaténée (jusqu'à une certaine limite). Voir la question Utilisation du point-virgule (;) vs plus (+) avec exec dans find pour plus d'informations à ce sujet.

johnny
la source
16
Utiliser +au lieu de \;, cela améliorera considérablement le temps d'exécution (puisqu'il contaténera les arguments avant l'exécution jusqu'à ARG_MAX).
Chris Down
Maintenant je comprends le pouvoir de xargs! Merci!
Domih
5
Utilisez cette option grep -Hsi vous souhaitez inclure le nom de fichier du fichier dans la sortie.
Steinar
18

Si vous souhaitez enregistrer toutes les lignes correspondantes dans tous les fichiers output.txt, votre dernière commande fonctionne, sauf qu'il vous manque l'élément requis ;à la fin de la commande.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

Si vous voulez que chaque exécution de grepgénère une sortie dans un fichier différent, exécutez un shell pour calculer le nom du fichier de sortie et effectuer la redirection.

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
Gilles, arrête de faire le mal
la source
le dernier vraiment sympa: D
bakytn
Pour développer la réponse @gilles et la rendre un peu plus informative, en particulier si la liste de fichiers que vous traitez est longue, vous pouvez indiquer le nom de fichier (chemin relatif) de chaque fichier avec les résultats affichés en utilisant cette fonction. : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt Et si vous souhaitez voir les numéros de ligne des lignes grises, vous pouvez bien sûr utilisergrep -n "something"
JJMpls le
9

Pour l'enregistrement, grepa --includeet les --excludearguments que vous pouvez utiliser pour filtrer les fichiers qu'il recherche:

grep -r --include="*.py" "something" > output.txt
hunse
la source
2
Au moins, GNU le grepfait.
phk
2

Utiliser tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

La mise en garde, est de savoir si vous avez des fichiers avec des caractères spéciaux (y compris les espaces) qui xargset grepne fonctionne pas bien avec ( a file.txtsera interprété comme deux fichiers, aet file.txt). L'alternative à cela est d'utiliser le -xou -print0, mais l'un ou l' autre vous polluerait output.txt. Le -xutilisera \pour échapper à certains caractères spéciaux et ce sera dans output.txt. Le -print0utilisera un octet nul en tant que séparateur de champ (ce qui nécessite également xargs -0) et output.txtressemblera à une longue ligne de texte contiguë.

Comment vous traitez (ou pas) avec ceci est à vous.

bahamat
la source