2013-03-01 14 views
5

grep ha la possibilità di cercare in modo ricorsivo utilizzando l'opzione -r. Tuttavia, mi chiedevo se grep ha la capacità di cercare una stringa di query in modo ricorsivo per un numero specificato di livelli di sottocartelle. Ad esempio, ho una cartella root che contiene le cartelle parent1, parent2, ..., parentN. Ogni cartella principale ha normali file di testo e cartelle chiamate child1, child2, ..., childM. Mi piacerebbe eseguire grep dal livello di root e cercare nei file all'interno dei genitori senza guardare nelle cartelle figlio. C'è un modo semplice per fare questo?Utilizzo di grep in modo ricorsivo

+1

si desidera fare qualcosa di simile: trovare/percorso/per/trovare-nome "nome del file" o desidera cat ogni file in controllare una stringa? –

risposta

6

si può provare questi fuori:

grep:

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

     --exclude-from=FILE 
       Skip files whose base name matches any of the file-name 
       globs read from FILE (using wildcard matching as 
       described under --exclude). 

     --exclude-dir=DIR 
       Exclude directories matching the pattern DIR from 
       recursive searches. 

o utilizzare questo find | xargs grep

con find, è possibile definire il livello di

EDIT

output pipe di un comando a un altro è molto comune nel mondo linux/unix. Scommetto che lo fai tutti i giorni.

echo "abc"|sed 's/a/x/' 
find . -name "*.pyc" |xargs rm 
awk 'blahblah' file | sort |head -n2 
tree|grep 'foo' 
mvn compile|ack 'error' 
... 

Si noti che non tutti gli esempi sopra riportati sono efficienti. Sono solo esempi.

+0

Grazie per la rapida risposta. Potresti spiegare che cos'è il | significa nel tuo esempio. So che può essere usato per convogliare l'output a un dest, ma non capisco come abbia senso collegare l'output a un comando diverso. In ogni caso, sto provando la tua soluzione e accetterò presto la tua risposta. – Sal

+0

@Sal vedi modifica in risposta, più pipe – Kent

10

As Kentnotes, non è possibile farlo con un dritto grep; semplicemente non è abbastanza potente. Il trucco è utilizzare find per individuare i file da cercare e passare l'elenco di file che produce find a grep.

Se si esegue man find, si otterrà una pagina man dei molte opzioni che find prende. Quello che ci interessa qui è -maxdepth.

Costruiamo il comando di cui abbiamo bisogno. Eseguire i comandi in ogni fase per vedere come si presenta:

  • find . elencherà tutti i file e le cartelle presenti nella cartella corrente (.) o qualsiasi cartella discendente.

  • find . -maxdepth 1 elencherà tutti i file e le cartelle nella cartella corrente. Allo stesso modo, find . -maxdepth 2 elenca tutti i file e le cartelle nella cartella corrente e qualsiasi sottocartella immediata. E così via ...

  • Nota che stiamo anche recuperando le cartelle; non vogliamo che questo, come grep non può cercare una cartella stessa, solo i file nella cartella. Aggiungi -type f per ottenere solo i file elencati: find . -maxdepth 2 -type f.

Ora sappiamo che il file che vogliamo cercare, abbiamo bisogno di ottenere grep per cercare quei file.Il metodo standard per farlo è usare xargs:

find . -maxdepth 2 -type f | xargs grep <text-to-search-for> 

Il | prende "standard output", alias "stdout", da find (cioè quello che normalmente si vede sullo schermo) e tubi in xarg s' "standard input ", aka" stdin ", cioè cosa accadrebbe normalmente se si stesse digitando un programma in esecuzione.

xargs è un astuto programma che esegue qualsiasi cosa tu gli dica (qui, grep <text-to-search-for>), dopo aver aggiunto tutti gli argomenti ricevuti su stdin. Il risultato è che grep cercherà tutti i file trovati da find.

Questo non funziona se alcuni dei nomi dei file contengono spazi, tuttavia, poiché lo xargs pensa che lo spazio stia separando due nomi di file diversi, piuttosto che una parte di un nome di file. Ci sono molti modi per gestirlo (l'ideale è semplicemente non usare spazi nei nomi dei file), e quello comune è usare una delle più fantasiose funzionalità di find.

Se si aggiunge un argomento -exec per find, eseguirà tutto il specificare fino a un ; o +. Se aggiungi un {} (ovvero i caratteri letterali { e }), questo verrà sostituito con un elenco di tutti i file. Dato che lo sta facendo find, sa che gli spazi nel nome del file dovrebbero essere nel nome del file.

Quindi il modo migliore per fare ciò che si sta cercando di è quindi:

find . -type f -maxdepth 2 -exec grep <text-to-search-for> {} + 

(La differenza tra termina con + e ; fa differenza qui Se siete interessati è nel man find, ma. la versione breve è quella + è più veloce ma significa che è possibile avere solo uno {} nel comando.)

Problemi correlati