Quando voglio cercare un intero albero per alcuni contenuti, uso
find . -type f -print0 | xargs -0 grep <search_string>
C'è un modo migliore per farlo in termini di prestazioni o brevità?
Quando voglio cercare un intero albero per alcuni contenuti, uso
find . -type f -print0 | xargs -0 grep <search_string>
C'è un modo migliore per farlo in termini di prestazioni o brevità?
Risposte:
Controlla se la tua opzione di grep
supporto -r
(per il recurse )
grep -r <search_string> .
--exclude-dir
per affrontare le prestazioni e abbiamo un vincitore!
grep
nelle recenti distribuzioni FreeBSD e Linux lo supportano. E perchè --exclude-dir
? Non hai chiesto di cercare un intero albero ?
--exclude-dir
è effettivamente utile nel mio caso d'uso (perché parti del sottostruttura sono grandi, ma inutili) e ho chiesto informazioni sulle prestazioni ... ma hai ragione, non è necessario.
--exclude-dir
è esclusivo di GNU grep
. (-:
Una risposta subottimale: anziché eseguire il piping dell'output di find
into grep
, è possibile eseguire
find . -type f -exec grep 'research' {} '+'
e voilà, un comando invece di due!
spiegazione :
find . -type f
trova tutti i file regolari all'interno.
-exec grep 'research'
grep "ricerca"
{}
nel nome file trovato
'+'
usa un comando per tutti i nomi di file, non una volta per nome file.
Nb: con ';'
esso sarebbe stato una volta per nome file.
A parte questo, se lo usi per elaborare il codice sorgente, puoi esaminare ack
quale è fatto per cercare facilmente i bit di codice.
Modificare :
Puoi estendere un po 'quella ricerca. Innanzitutto, è possibile utilizzare l' opzione -name ''
di find
per cercare i file con un modello di denominazione specifico.
Per esempio :
solo i file che corrispondono ai registri: -name '*.log'
solo i file che corrispondono alle intestazioni c, ma non è possibile utilizzare maiuscole o minuscole per le estensioni dei nomi: -iname *.c
Nb: come per grep
e ack
, l' -i
interruttore significa maiuscole e minuscole in questo caso.
In tal caso, grep verrà visualizzato senza colore e senza numeri di riga.
Si può cambiare la situazione con l' --color
ei -n
interruttori (numeri di colore e linee in file, rispettivamente).
Alla fine, puoi avere qualcosa del tipo:
find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
per esempio
$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+'
./test2/target.c:1:hello
-name '*.log'
È più veloce.
Se vuoi rientrare nelle sottodirectory:
grep -R 'pattern' .
L' -R
opzione non è un'opzione standard, ma è supportata dalle grep
implementazioni più comuni .
-r
invece di -R
saltare i collegamenti simbolici quando GNU grep è interessato
grep
implementazioni GNU catturano ricorsioni, penso. Altrimenti dipende da cosa intendi per "albero".
grep
dovrebbe fare. Se l'utente ha anelli simbolici nella struttura della directory, beh, questo è il problema dell'utente :-)
/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...
(-XI come strumenti che mi fanno da babysitter (a meno che non forniscano strana magia che chiamano "AI"). (-;
Come notato sopra -r
o -R
(a seconda della gestione dei collegamenti simbolici desiderata) è un'opzione rapida.
Tuttavia -d <action>
a volte può essere utile.
La cosa bella -d
è il comando skip, che mette a tacere "grep: nome_directory: è una directory" quando si desidera solo scansionare il livello corrente.
$ grep foo *
grep: q2: Is a directory
grep: rt: Is a directory
$ grep -d skip foo *
$
ed ovviamente:
$ 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
opzione è DAVVERO utile all'interno di un altro script, quindi non è necessario 2> /dev/null
. :)
Se hai a che fare con molti file, grep viene eseguito più velocemente se elimini i file di cui ha bisogno per cercare invece di eseguire il grepping di tutti i file nelle sottocartelle.
Uso questo formato a volte:
grep "primary" `find . | grep cpp$`
Trova tutti i file nelle sottocartelle .
che terminano in cpp
. Quindi grep quei file per "primario".
Se lo desideri, puoi continuare a convogliare questi risultati in ulteriori chiamate grep:
grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"