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é?
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é?
Réponses:
Vérifiez si votre option de grep
soutien -r
(pour les infirmières ):
grep -r <search_string> .
--exclude-dir
pour aborder la performance et nous avons un gagnant!
grep
sur les distributions récentes FreeBSD et Linux le supportent. Et pourquoi --exclude-dir
? N'avez-vous pas demandé de rechercher un arbre entier ?
--exclude-dir
est 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.
--exclude-dir
est exclusif à GNU grep
. (-:
Une réponse sous-optimale: au lieu de canaliser la sortie de find
dans 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 ack
ce qui est fait pour rechercher facilement des bits de code.
Modifier :
Vous pouvez étendre un peu cette recherche. Tout d'abord, vous pouvez utiliser le -name ''
commutateur de find
pour 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 grep
et ack
, le -i
commutateur 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 --color
et les -n
commutateurs (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
-name '*.log'
c'est plus rapide.
Si vous souhaitez rentrer dans les sous-répertoires:
grep -R 'pattern' .
L' -R
option n'est pas une option standard, mais est prise en charge par la plupart des grep
implémentations courantes .
-r
au lieu de -R
pour ignorer les liens symboliques lorsque GNU grep est concerné
grep
implémentations GNU actuelles attrapent des récursions, je pense. Sinon, cela dépend de ce que vous entendez par "arbre".
grep
devrait 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 :-)
/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"). (-;
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 -d
est 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 skip
option est VRAIMENT pratique dans un autre script pour que vous n'ayez pas à le faire 2> /dev/null
. :)
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"