Comment exclure des répertoires de grep -R?

670

Je souhaite parcourir tous les sous-répertoires, à l'exception du répertoire "node_modules".

TIMEX
la source
3
Voir superuser.com/q/66715/59933
borrible
14
Tapez simplement "man grep" et vous verrez les options --exclude et --exclude-dir listées juste là - à partir du titre de cette question, je suppose que vous connaissiez déjà grep ...
arcseldon
35
Si vous Grepping pour le code dans un dépôt git et node_modulesest dans votre .gitignore, git grep "STUFF"est la meilleure façon. git greprecherche les fichiers suivis dans l'arborescence de travail, ignorant tout de.gitignore
0xcaff
2
Un exemple pour node: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- en outre, vous pouvez toujours alias ceci dans le shell pour 'nodegrep' ou autre chose et utiliser un argument de commande comme entrée de chaîne ..
bshea

Réponses:

395

SOLUTION 1 (combiner findet grep)

Le but de cette solution n'est pas de traiter les grepperformances mais de montrer une solution portable: devrait également fonctionner avec busybox ou une version GNU antérieure à 2.5.

Utilisez find, pour exclure les répertoires foo et bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Combinez ensuite findet l'utilisation non récursive de grep, comme solution portable:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

SOLUTION 2 (utilisation récursive de grep):

Vous connaissez déjà cette solution, mais je l'ajoute car c'est la solution la plus récente et la plus efficace. Notez qu'il s'agit d'une solution moins portable mais plus lisible par l'homme.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Pour exclure plusieurs répertoires, utilisez --exclude-dircomme:

--exclude-dir={node_modules,dir1,dir2,dir3}

SOLUTION 3 (Ag)

Si vous recherchez fréquemment du code, Ag (The Silver Searcher) est une alternative beaucoup plus rapide à grep, qui est personnalisée pour la recherche de code. Par exemple, il ignore automatiquement les fichiers et répertoires répertoriés dans .gitignore, vous n'avez donc pas à passer les mêmes options d'exclusion lourdes à grepou find.

hornetbzz
la source
2
cette combinaison recherche plus vite que --exclude-dir=diret elle montre des résultats avec des couleurs - facile à lire
Maxim Yefremov
27
"cette combinaison" find ... -execn'est pas plus rapide que grep --exclude-dirpour moi. Un énorme avantage pour grep (environ cinq fois plus rapide avec 26k + fichiers, filtré sur 38k + sur un disque dur), sauf si vous remplacez le \;par +pour le combo find / exec. Grep est alors "seulement" environ 30% plus rapide. La syntaxe grep est également lisible par l'homme :).
Kjell Andreassen
D'accord, car cela est évident. Certaines boîtes occupées n'ont pas la commande GREP.
hornetbzz
10
notant également que vous pouvez exclure plusieurs avec--exclude-dir={dir1,dir2}
suh
4
Je ne suis pas le moins du monde surpris que ce node_modulessoit l'exemple canonique.
pdoherty926
984

Les versions récentes de GNU Grep (> = 2.5.2 ) fournissent:

--exclude-dir=dir

ce qui exclut les répertoires correspondant au modèle dirdes recherches de répertoires récursives.

Vous pouvez donc faire:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Pour un peu plus d'informations sur la syntaxe et l'utilisation, voir

Pour les anciens GNU Greps et POSIX Grep , utilisez findcomme suggéré dans d'autres réponses.

Ou utilisez simplement ack( Edit : ou The Silver Searcher ) et terminez!

Johnsyweb
la source
4
@Manocho: Si vous pensez que ackc'est génial, essayez The Silver Searcher et voyez la vitesse augmenter!
Johnsyweb
30
Syntaxe pour les impatients: --exclude-dir=dirutilise greples modèles d'expression régulière de, et non la globalisation des fichiers du shell. Les modèles fonctionnent sur les chemins relatifs à votre répertoire actuel. Utilisez donc le modèle --exclude-dir=dir, non --exclude-dir="/root/dir/*".
tanius
15
Si vous souhaitez exclure plusieurs répertoires de la recherche, y a-t-il une meilleure option que d'utiliser $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darshan Chaudhary
4
J'ai probablement passé beaucoup trop de temps à ce sujet que n'importe quelle personne sensée, mais je ne peux pas pour la vie de moi comprendre comment exclure un sous-répertoire de la recherche - grep -r --exclude-dir=public keyword .fonctionne, mais grep -r --exclude-dir='public/dist' keyword .ne le fait pas. J'ai essayé d'ajouter des caractères génériques regex, des caractères d'échappement, etc., mais rien ne semble aider.
dkobozev
73
Exclure plusieurs répertoires comme ceci:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
78

Si vous souhaitez exclure plusieurs répertoires :

"r" pour récursif, "l" pour imprimer uniquement les noms des fichiers contenant des correspondances et "i" pour ignorer les distinctions de casse:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Exemple: je souhaite rechercher des fichiers contenant le mot «bonjour». Je veux rechercher dans tous mes répertoires linux sauf le répertoire proc , le répertoire de démarrage , le répertoire sys et le répertoire racine :

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Remarque: l'exemple ci-dessus doit être root

Note 2 (selon @skplunkerin): n'ajoutez pas d'espaces après les virgules dans {dir1,dir2,dir3}

Azodium
la source
5
REMARQUE: n'ajoutez pas d'espaces après les virgules{dir1,dir2,dir3}
skplunkerin
Merci, pratique lorsque vous parcourez l'espace de travail SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Vous pouvez simplement fournir l' --exclude-diroption plusieurs fois.
Walf
45

Cette syntaxe

--exclude-dir={dir1,dir2}

est développé par le shell (par exemple Bash), pas par grep, en ceci:

--exclude-dir=dir1 --exclude-dir=dir2

Citer empêchera le shell de le développer, donc cela ne fonctionnera pas:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Les modèles utilisés avec --exclude-dirsont les mêmes types de modèles décrits dans la page de manuel de l' --excludeoption:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Le shell essaie généralement de développer un tel modèle lui-même, donc pour éviter cela, vous devez le citer:

--exclude-dir='dir?'

Vous pouvez utiliser les accolades et les motifs d'exclusion cités ensemble comme ceci:

--exclude-dir={'dir?','dir??'}

Un motif peut s'étendre sur plusieurs segments de chemin:

--exclude-dir='some*/?lse'

Cela exclurait un répertoire comme topdir/something/else.

Derek Veit
la source
14

Utilisez fréquemment ceci:

greppeut être utilisé conjointement avec -r(récursif), i(ignorer la casse) et -o(imprime uniquement une partie correspondante des lignes). Pour exclure l' filesutilisation --excludeet exclure l'utilisation des répertoires --exclude-dir.

En l'assemblant, vous vous retrouvez avec quelque chose comme:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Le décrire le rend beaucoup plus compliqué qu'il ne l'est réellement. Plus facile à illustrer avec un exemple simple.

Exemple:

Supposons que je recherche le projet en cours pour tous les endroits où j'ai explicitement défini la valeur de la chaîne debuggerlors d'une session de débogage et que je souhaite maintenant réviser / supprimer.

J'écris un script appelé findDebugger.shet utilise greppour trouver toutes les occurrences. Toutefois:

Pour les exclusions de fichiers - je souhaite m'assurer que cela .eslintrcest ignoré (cela a en fait une règle sur les peluches debuggeret doit donc être exclu). De même, je ne veux pas que mon propre script soit référencé dans les résultats.

Pour les exclusions de répertoires - je souhaite exclure node_modulescar il contient de nombreuses bibliothèques qui font référence debuggeret je ne suis pas intéressé par ces résultats. Aussi je voudrais juste Omettre .ideaet .gitrépertoires cachés parce que je ne me soucie pas de ces lieux de recherche non plus , et je souhaite de garder la recherche performant.

Voici donc le résultat - je crée un script appelé findDebugger.shavec:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
la source
Je crois que l'option "r" devrait être imprimée avec un "-R" majuscule.
hornetbzz
1
Intéressant. "r" a toujours fonctionné pour moi sur nix et mac.
arcseldon
Quand j'ai écrit ma réponse , j'ai utilisé -R(je ne me souviens plus pourquoi maintenant). J'utilise généralement -r. Il s'avère que la version majuscule suit les liens symboliques . TIL.
Johnsyweb
@Johnsyweb - merci. a voté pour votre réponse - ne me souviens pas quand, probablement en 2016 quand j'ai ajouté celui-ci :)
arcseldon
10

Vous pourriez essayer quelque chose comme grep -R search . | grep -v '^node_modules/.*'

Commutateur DIP
la source
34
Pas une bonne solution dans certains cas. Par exemple: si le répertoire 'node_modules' est énorme avec beaucoup de fausses correspondances positives (d'où la nécessité de filtrer le répertoire), alors le premier grep perd beaucoup de temps à chercher dans un sous-répertoire et ALORS le deuxième filtrage grep les matchs. Il est plus rapide d'exclure node_modules dans le premier grep lui-même.
GuruM
2
je ne me soucie pas de la lenteur, je peux regarder la commande et savoir ce qu'elle fait
Funkodebat
1
Idem pour le commentaire de Guru. Un grep de se /varbloque quand il frappe /var/rundans mon cas. D'où la raison pour laquelle je veux éviter le répertoire en premier lieu.
2015 à 9h48
3
--exclude-direst la meilleure solution à partir de 2016.
Omar Tariq
10

Si vous Grepping pour le code dans un dépôt git et node_modulesest dans votre .gitignore, vous pouvez utiliser git grep. git greprecherche les fichiers suivis dans l'arborescence de travail, ignorant tout de.gitignore

git grep "STUFF"
0xcaff
la source
C'est une astuce très utile. Merci.
NKM
4

Très utile, surtout pour ceux qui traitent avec Node.js où nous voulons éviter de chercher dans "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Nestor Urquiza
la source
2

Une commande de travail simple:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Ci-dessus, je demande le texte "creativecommons.org" dans le répertoire courant "dspace" et j'exclus les répertoires {log, assetstore}.

Terminé.

Fumier
la source
Propre, y compris plusieurs répertoires entre parenthèses
Mijo
2

Beaucoup de bonnes réponses ont été données ici, mais j'ajoute celle-ci pour souligner un point qui a provoqué l'échec de certaines tentatives précipitées: exclude-dirprend un modèle , pas un chemin vers un répertoire.

Dites que votre recherche est:

grep -r myobject

Et vous remarquez que votre sortie est encombrée de résultats du src/other/objects-folder. Cette commande ne vous donnera pas le résultat souhaité:

grep -r myobject --exclude-dir=src/other/objects-folder

Et vous vous demandez peut-être pourquoi ça exclude-dirne marche pas! Pour exclure réellement les résultats de la objects-folder, procédez simplement comme suit:

grep -r myobject --exclude-dir=objects-folder

En d'autres termes, utilisez simplement le nom du dossier , pas le chemin d'accès. Évident une fois que vous le savez.

Depuis la page de manuel:

--exclude-dir = GLOB Ignore
tout répertoire de ligne de commande avec un suffixe de nom qui correspond au modèle GLOB. Lors d'une recherche récursive, ignorez tout sous-répertoire dont le nom de base correspond à GLOB. Ignorez toutes les barres obliques redondantes dans GLOB.

Nagev
la source
2

Celui-ci fonctionne pour moi:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
la source
5
En quoi cette réponse est-elle différente de ce qui a déjà été publié?
aexl
1
find . ! -name "node_modules" -type d 
Jack
la source
-1

Une manière plus simple serait de filtrer vos résultats en utilisant "grep -v".

grep -i needle -R * | grep -v node_modules

Morris
la source
12
C'est en fait la même réponse que DipSwitch a fournie 3 ans plus tôt. Il a également les mêmes problèmes.
JWW