Come posso escludere le directory da grep -R?


670

Voglio attraversare tutte le sottodirectory, tranne la directory "node_modules".



14
Basta digitare "man grep" e vedrai le opzioni --exclude e --exclude-dir elencate proprio lì - dall'intestazione di questa domanda, presumo che tu abbia già saputo di grep ...
arcseldon

35
Se stai cercando il codice in un repository git ed node_modulesè nel tuo .gitignore, git grep "STUFF"è il modo più semplice. git grepcerca i file tracciati nell'albero di lavoro, ignorando tutto da.gitignore
0xcaff,

2
Un esempio per il nodo: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- inoltre puoi sempre alias questo nella shell a 'nodegrep' o altro e usare un argomento di comando come input di stringa ..
bshea

Risposte:


395

SOLUZIONE 1 (combinare findegrep )

Lo scopo di questa soluzione non è di occuparsene grep prestazioni ma di mostrare una soluzione portatile: dovrebbe funzionare anche con la versione busybox o GNU precedente alla 2.5.

Utilizzare find, per escludere le directory foo e bar:

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

Quindi combinare finde l'uso non ricorsivo di grep, come soluzione portatile:

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

SOLUZIONE 2 (uso ricorsivo di grep):

Conosci già questa soluzione, ma la aggiungo poiché è la soluzione più recente ed efficiente. Nota che questa è una soluzione meno portatile ma più leggibile dall'uomo.

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

Per escludere più directory, utilizzare --exclude-dircome:

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

SOLUZIONE 3 (Ag)

Se cerchi frequentemente il codice, Ag (The Silver Searcher) è un'alternativa molto più veloce a grep, che è personalizzata per la ricerca del codice. Ad esempio, ignora automaticamente i file e le directory elencati in .gitignore, quindi non è necessario continuare a passare le stesse ingombranti opzioni di esclusione a grepo find.


2
questa combinazione cerca più velocemente di --exclude-dir=dire mostra risultati con colori - facili da leggere
Maxim Yefremov

27
"questa combinazione" find ... -execnon è più veloce di grep --exclude-dirme. Enorme vantaggio di grep (circa cinque volte più veloce con 26k + file, filtrato su 38k + su un HDD), a meno che non lo si sostituisca \;con +il combo find / exec. Quindi grep è "solo" circa il 30% più veloce. La sintassi grep è anche leggibile dall'uomo :).
Kjell Andreassen,

D'accordo, poiché questo è ovvio. Alcune caselle di occupato non hanno il comando GREP.
Hornetbzz,

10
notando anche che puoi escludere il multiplo con--exclude-dir={dir1,dir2}
suh,

4
Non sono minimamente sorpreso che node_modulessia l'esempio canonico.
pdoherty926,

984

Le versioni recenti di GNU Grep (> = 2.5.2 ) forniscono:

--exclude-dir=dir

che esclude le directory corrispondenti allo schema dirdalle ricerche ricorsive di directory.

Quindi puoi fare:

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

Per ulteriori informazioni sulla sintassi e sull'utilizzo, consultare

Per GNU Greps precedenti e POSIX Grep , utilizzare findcome suggerito in altre risposte.

O semplicemente usa ack( Modifica : o The Silver Searcher ) e finisci!


4
@Manocho: se pensi che acksia fantastico, prova The Silver Searcher e vedi aumentare la velocità!
Johnsyweb,

30
Sintassi per l'impaziente: --exclude-dir=dirusa grepi modelli di espressione regolare, non il globbing dei file della shell. I pattern funzionano su percorsi relativi alla directory corrente. Quindi usa il modello --exclude-dir=dir, no --exclude-dir="/root/dir/*".
tanius,

15
Se si desidera escludere più directory dalla ricerca, esiste un'opzione migliore che utilizzare $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darshan Chaudhary,

4
Probabilmente ho trascorso troppo tempo su questo rispetto a qualsiasi persona sana di mente, ma non posso per la vita di me capire come escludere una sottodirectory dalla ricerca - grep -r --exclude-dir=public keyword .funziona, ma grep -r --exclude-dir='public/dist' keyword .non lo fa. Ho provato ad aggiungere jolly regex, caratteri di escape ecc., Ma nulla sembra aiutare.
dkobozev,

73
Escludere più directory in questo modo:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

78

Se si desidera escludere più directory :

"r" per ricorsivo, "l" per stampare solo i nomi dei file contenenti corrispondenze e "i" per ignorare le distinzioni maiuscole:

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

Esempio: voglio trovare file che contengono la parola 'ciao'. Voglio cercare in tutte le mie directory di Linux tranne la directory proc , la directory di avvio , la directory sys e la directory root :

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

Nota: l'esempio sopra deve essere root

Nota 2 (secondo @skplunkerin): non aggiungere spazi dopo le virgole {dir1,dir2,dir3}


5
NOTA: non aggiungere spazi dopo le virgole in{dir1,dir2,dir3}
skplunkerin

Grazie, utile quando si passa attraverso l'area di lavoro SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237

1
Puoi semplicemente fornire l' --exclude-diropzione più volte.
Walf,

45

Questa sintassi

--exclude-dir={dir1,dir2}

viene espanso dalla shell (ad esempio Bash), non da grep, in questo:

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

La quotazione impedirà alla shell di espanderla, quindi non funzionerà:

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

I modelli utilizzati --exclude-dirsono dello stesso tipo di modelli descritti nella pagina man per l' --excludeopzione:

--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.

La shell generalmente tenterà di espandere un tale modello stesso, quindi per evitarlo, dovresti citarlo:

--exclude-dir='dir?'

Puoi usare le parentesi graffe e gli schemi di esclusione citati insieme in questo modo:

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

Un modello può comprendere più segmenti di percorso:

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

Ciò escluderebbe una directory come topdir/something/else.


14

Usa frequentemente questo:

greppuò essere utilizzato insieme a -r(ricorsivo), i(ignora maiuscole e minuscole) e -o(stampa solo la parte corrispondente delle linee). Per escludere l' filesuso --excludee per escludere le directory utilizzare --exclude-dir.

Mettendolo insieme si finisce con qualcosa del tipo:

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

Descriverlo rende il suono molto più complicato di quanto non sia in realtà. Più facile da illustrare con un semplice esempio.

Esempio:

Supponiamo che sto cercando il progetto corrente per tutti i luoghi in cui ho impostato esplicitamente il valore della stringa debuggerdurante una sessione di debug e ora desidero rivedere / rimuovere.

Scrivo uno script chiamato findDebugger.she lo uso grepper trovare tutte le occorrenze. Però:

Per le esclusioni di file - Desidero assicurarmi che .eslintrcvenga ignorato (questo in realtà ha una regola di linting al riguardo, debuggerquindi dovrebbe essere escluso). Allo stesso modo, non voglio che il mio script venga referenziato in nessun risultato.

Per le esclusioni di directory: desidero escludere node_modulespoiché contiene molte librerie che fanno riferimento debuggere non sono interessato a tali risultati. Inoltre, desidero solo omettere .ideae .gitnascondere le directory perché non mi interessa nemmeno quelle posizioni di ricerca e desidero mantenere la ricerca performante.

Quindi ecco il risultato: creo uno script chiamato findDebugger.shcon:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .

Credo che l'opzione "r" dovrebbe essere stampata con una maiuscola "-R".
Hornetbzz,

1
Interessante. "r" ha sempre funzionato per me su nix e mac.
ArcSeldon,

Quando ho scritto la mia risposta , ho usato -R(non ricordo perché adesso). Io di solito uso -r. Si scopre che la versione maiuscola segue i collegamenti simbolici . TIL.
Johnsyweb,

@Johnsyweb - grazie. ha votato positivamente la tua risposta - non ricordare quando, probabilmente nel 2016, quando ho aggiunto questo :)
arcseldon,

10

Potresti provare qualcosa del genere grep -R search . | grep -v '^node_modules/.*'


34
Non è una buona soluzione in alcuni casi. Ad esempio: se la directory 'node_modules' è enorme con molte corrispondenze false positive (quindi la necessità di filtrare la directory), il primo grep sta sprecando molto tempo a cercare in una sotto-directory e POI il secondo filtro grep fuori le partite. È più veloce escludere node_modules nel primo grep stesso.
GuruM,

2
non mi interessa la lentezza, posso guardare il comando e sapere cosa fa
Funkodebat

1
Idem per il commento di Guru. Un /varcolpo di frusta quando colpisce /var/runnel mio caso. Da qui il motivo per cui voglio evitare la directory in primo luogo.
jww

3
--exclude-dirè la soluzione migliore a partire dal 2016.
Omar Tariq,

10

Se stai cercando il codice in un repository git ed node_modulesè nel tuo .gitignore, puoi usarlo git grep. git grepcerca i file tracciati nell'albero di lavoro, ignorando tutto da.gitignore

git grep "STUFF"

Questo è un consiglio molto utile.Grazie.
NKM,

4

Molto utile, specialmente per coloro che hanno a che fare con Node.js dove vogliamo evitare di cercare all'interno di "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword

2

Un semplice comando funzionante:

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

Sopra ho grep per il testo "creativecommons.org" nella directory corrente "dspace" ed escludo dirs {log, assetstore}.

Fatto.


Ordinato, tra cui diverse directory tra parentesi
Mijo,

2

Qui sono state fornite molte risposte corrette, ma sto aggiungendo questa per enfatizzare un punto che ha causato prima alcuni tentativi affrettati: exclude-dirprende un modello , non un percorso in una directory.

Dì che la tua ricerca è:

grep -r myobject

E noti che il tuo output è ingombro di risultati dal src/other/objects-folder. Questo comando lo farà non ti darà il risultato desiderato:

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

E potresti chiederti perché exclude-dir non funziona! Per escludere effettivamente i risultati dal objects-folder, basta fare questo:

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

In altre parole, basta usare il nome della cartella , non il percorso. Ovvio una volta che lo sai.

Dalla pagina man:

--exclude-dir = GLOB
Salta qualsiasi directory della riga di comando con un suffisso del nome che corrisponda al modello GLOB. Durante la ricerca ricorsiva, saltare qualsiasi sottodirectory il cui nome di base corrisponde a GLOB. Ignora eventuali barre finali ridondanti in GLOB.


2

Questo funziona per me:

grep <stuff> -R --exclude-dir=<your_dir>

5
In che modo questa risposta è diversa da ciò che è già stato pubblicato?
aexl,

1
find . ! -name "node_modules" -type d 

-1

Un modo più semplice sarebbe filtrare i risultati usando "grep -v".

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


12
Questa è effettivamente la stessa risposta DipSwitch fornita 3 anni prima. Ha anche gli stessi problemi.
JWW
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.