Existe-t-il un moyen plus simple de grep tous les fichiers d'un répertoire?


21

Lorsque je souhaite rechercher un contenu dans un arbre entier, j'utilise

find . -type f -print0 | xargs -0 grep <search_string>

Existe-t-il une meilleure façon de procéder en termes de performances ou de brièveté?


2
@Downvoter: Heureux d'améliorer cette question si vous pouvez partager vos préoccupations.
Dancrumb

2
de nombreuses versions de find ont des xargs intégrés: find. -type f -exec fgrep <search_string> {} +
simpleuser

Réponses:


42

Vérifiez si votre option de grepsoutien -r(pour les infirmières ):

grep -r <search_string> .

1
Yup ... Je viens de trouver stackoverflow.com/questions/16956810/… et c'est la réponse là aussi.
Dancrumb

ajoutez un commentaire sur --exclude-dirpour aborder la performance et nous avons un gagnant!
Dancrumb

1
Notez juste que ce n'est pas portable, cependant grepsur les distributions récentes FreeBSD et Linux le supportent. Et pourquoi --exclude-dir? N'avez-vous pas demandé de rechercher un arbre entier ?
Philippos

Juste point ... --exclude-direst en fait pratique dans mon cas d'utilisation (parce que certaines parties du sous-arbre sont grandes, mais inutiles) et j'ai posé des questions sur les performances ... mais vous avez raison, ce n'est pas nécessaire.
Dancrumb

Dans ce cas, je dois ajouter que l'IIRC --exclude-direst exclusif à GNU grep. (-:
Philippos

13

Une réponse sous-optimale: au lieu de canaliser la sortie de finddans grep, vous pouvez simplement exécuter

find . -type f -exec grep 'research' {} '+'

et le tour est joué, une commande au lieu de deux!

explication:

find . -type f

trouver tous les fichiers réguliers dans.

-exec grep 'research'

grep 'recherche'

{}

dans le nom de fichier trouvé

'+'

utilisez une commande pour tous les noms de fichiers, pas une fois par nom de fichier.

Nb: avec ';'cela aurait été une fois par nom de fichier.

En dehors de cela, si vous l'utilisez pour traiter le code source, vous pouvez examiner ackce qui est fait pour rechercher facilement des bits de code.

ack

Modifier :

Vous pouvez étendre un peu cette recherche. Tout d'abord, vous pouvez utiliser le -name ''commutateur de findpour rechercher des fichiers avec un modèle de dénomination spécifique.

Par exemple :

  • seuls les fichiers qui correspondent aux journaux: -name '*.log'

  • seuls les fichiers qui correspondent aux en-têtes c, mais vous ne pouvez pas vous en tenir en majuscules ou en minuscules pour vos extensions de nom de fichier: -iname *.c

Nb: comme pour grepet ack, le -icommutateur signifie insensible à la casse dans ce cas.

Dans ce cas, grep s'affichera sans couleur et sans numéro de ligne.

Vous pouvez changer cela avec le --coloret les -ncommutateurs (couleur et lignes numéros dans des fichiers respectivement).

En fin de compte, vous pouvez avoir quelque chose comme:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

par exemple

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello

5
ackest génial, et une version plus rapide de ackis ag(le chercheur d'argent, geoff.greer.fm/ag )
cfeduke

1
Je préfère cela avec un filtre comme -name '*.log'c'est plus rapide.
sdkks

@cfeduke Je ne l'ai pas essayé, principalement parce que ag ne fait pas partie des dépôts apt par défaut sur WSL (tu dois travailler avec ce que tu as!)
Pierre-Antoine Guillaume

Une astuce consiste à ajouter / dev / null au grep pour faire apparaître le nom de fichier.
ChuckCottrill

Une astuce consiste à rechercher uniquement les répertoires, puis -exec grep / dev / null {} / * pour obtenir tous les fichiers avec un seul fork / exec par répertoire.
ChuckCottrill

12

Si vous souhaitez rentrer dans les sous-répertoires:

grep -R 'pattern' .

L' -Roption n'est pas une option standard, mais est prise en charge par la plupart des grepimplémentations courantes .


7
Utilisez -rau lieu de -Rpour ignorer les liens symboliques lorsque GNU grep est concerné
αғsнιη

1
@AFSHIN Pourquoi ne voudriez-vous pas suivre les liens symboliques?
Kusalananda

4
@Kusalananda Recursion? Bien que les grepimplémentations GNU actuelles attrapent des récursions, je pense. Sinon, cela dépend de ce que vous entendez par "arbre".
Philippos

2
@Philippos IMHO, garder un utilisateur n'est pas quelque chose qu'un outil comme grepdevrait faire. Si l'utilisateur a des boucles de liens symboliques dans sa structure de répertoire, c'est bien le problème de l'utilisateur :-)
Kusalananda

3
@Kusalananda Et si le système fournissait la boucle? Je ne /sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...me suis jamais perdu dans (-XI comme des outils qui me gardent (à moins qu'ils ne fournissent une magie étrange qu'ils appellent "AI"). (-;
Philippos

5

Comme indiqué ci -r- dessus ou -R(selon la gestion souhaitée du lien symbolique) est une option rapide.

Cependant, cela -d <action>peut parfois être utile.

La bonne chose à propos -dest la commande skip, qui fait taire le "grep: nom_répertoire: est un répertoire" lorsque vous voulez simplement analyser le niveau actuel.

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 

et bien sûr:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 

L' -d skipoption est VRAIMENT pratique dans un autre script pour que vous n'ayez pas à le faire 2> /dev/null. :)


0

Si vous traitez un grand nombre de fichiers, le grep s'exécute plus rapidement si vous élaguez les fichiers dont il a besoin de rechercher plutôt que de saluer tous les fichiers dans les sous-dossiers.

J'utilise parfois ce format:

grep "primary" `find . | grep cpp$`

Trouvez tous les fichiers dans les sous-dossiers de .cette fin dans cpp. Ensuite, grep ces fichiers pour "primaire".

Si vous le souhaitez, vous pouvez continuer à canaliser ces résultats dans d'autres appels grep:

grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"

1
les backtics ne sont pas une bonne pratique moderne, ils sont presque obsolètes
Christopher

1
Cela se cassera si vous avez des fichiers avec des caractères spéciaux dans leurs noms. Je ne sais pas à quel point ils doivent être spéciaux pour être trop spéciaux pour que cela fonctionne tel quel, mais ce que vous faites est vraiment la même chose que d'analyser la sortie de ls, ce qui est également mauvais.
un CV
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.