Esiste un modo più semplice per eseguire il grep di tutti i file in una directory?


21

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à?


2
@Downvoter: felice di migliorare questa domanda se puoi condividere le tue preoccupazioni.
Dancrumb,

2
molte versioni di find hanno xargs integrato: find. -type f -exec fgrep <search_string> {} +
simpleuser

Risposte:


42

Controlla se la tua opzione di grepsupporto -r(per il recurse )

grep -r <search_string> .

1
Sì ... ho appena trovato stackoverflow.com/questions/16956810/… e questa è la risposta anche lì.
Dancrumb,

aggiungi un commento --exclude-dirper affrontare le prestazioni e abbiamo un vincitore!
Dancrumb,

1
Notate che questo non è portatile, tuttavia grepnelle recenti distribuzioni FreeBSD e Linux lo supportano. E perchè --exclude-dir? Non hai chiesto di cercare un intero albero ?
Philippos,

Il punto giusto ... --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.
Dancrumb,

In questo caso, devo aggiungere che IIRC --exclude-dirè esclusivo di GNU grep. (-:
Philippos,

13

Una risposta subottimale: anziché eseguire il piping dell'output di findinto 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 ackquale è fatto per cercare facilmente i bit di codice.

ack

Modificare :

Puoi estendere un po 'quella ricerca. Innanzitutto, è possibile utilizzare l' opzione -name ''di findper 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 grepe ack, l' -iinterruttore 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' --colorei -ninterruttori (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

5
ackè fantastico e una versione più veloce di ackis ag(il cercatore d'argento, geoff.greer.fm/ag )
cfeduke,

1
Preferisco questo con un filtro come -name '*.log'È più veloce.
sdkks

@cfeduke Non l'ho provato, soprattutto perché ag non fa parte dei repository apt predefiniti su WSL (devi lavorare con quello che hai!)
Pierre-Antoine Guillaume

Un trucco è aggiungere / dev / null al grep per far apparire il nome del file.
ChuckCottrill,

Un trucco è cercare solo le directory e quindi -exec grep / dev / null {} / * per ottenere tutti i file con fork singolo / exec per directory.
ChuckCottrill,

12

Se vuoi rientrare nelle sottodirectory:

grep -R 'pattern' .

L' -Ropzione non è un'opzione standard, ma è supportata dalle grepimplementazioni più comuni .


7
Usa -rinvece di -Rsaltare i collegamenti simbolici quando GNU grep è interessato
αғsнιη

1
@AFSHIN Perché non dovresti voler seguire i symlink?
Kusalananda

4
@Kusalananda Recursion? Anche se le attuali grepimplementazioni GNU catturano ricorsioni, penso. Altrimenti dipende da cosa intendi per "albero".
Philippos,

2
@Philippos IMHO, fare da baby-sitter all'utente non è qualcosa che uno strumento come grepdovrebbe fare. Se l'utente ha anelli simbolici nella struttura della directory, beh, questo è il problema dell'utente :-)
Kusalananda

3
@Kusalananda E se il sistema fornisse il loop? Non mi sono mai perso /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"). (-;
Philippos

5

Come notato sopra -ro -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 skipopzione è DAVVERO utile all'interno di un altro script, quindi non è necessario 2> /dev/null. :)


0

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"

1
i retroscena non sono una buona pratica moderna, sono quasi obsoleti
Christopher,

1
Questo si interromperà se hai file con caratteri speciali nei loro nomi. Non so quanto debbano essere speciali per essere troppo speciali perché funzioni così com'è, ma quello che stai facendo è davvero la stessa cosa che analizzare l'output di ls, il che è anche un male.
un CVn il
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.