Come posso greppare ricorsivamente?


1682

Come posso ricorsivamente greptutte le directory e le sottodirectory?

find . | xargs grep "texthere" *

110
@ TC1 La cosa triste è che grep stesso può rispondere alla domanda (almeno GNU grep): grep - aiuto | grep ricorsivo
Frank Schmitt,

7
Se ti ritrovi spesso ad usare grep per fare ricerche ricorsive (specialmente se fai molte estensioni di file / directory), potresti trovare utile ack (un'alternativa grep molto intuitiva per i programmatori).
Nick McCurdy,

19
In realtà né -r né - lavoro ricorsivo sulla scatola di Solaris che uso al lavoro. E la pagina man di grep non menziona nulla di ricorsivo. Ho dovuto ricorrere a trovare e xargs me stesso.
Ben

8
ag è il mio modo preferito per farlo ora github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plnon funziona per me su Redhat Linux. Viene visualizzato l'errore "Nessuna corrispondenza".
Bulrush,

Risposte:


2507
grep -r "texthere" .

Il primo parametro rappresenta l'espressione regolare da cercare, mentre il secondo rappresenta la directory da cercare. In questo caso, .indica la directory corrente.

Nota: questo funziona con GNU grep e su alcune piattaforme come Solaris è necessario utilizzare GNU grep invece dell'implementazione legacy. Per Solaris questo è il ggrepcomando.


39
Nota: "grep -r" funziona solo su grep più recenti. Non funziona sul grep che viene fornito AIX 5.3ad esempio.
Trattenuto il

110
Usa grep -R per seguire i symlink.
Eloff,

53
È bene sapere che "-i" non farebbe distinzione tra maiuscole e minuscole e "-n" include anche il numero di riga per ogni risultato corrispondente.
Sadegh,

24
anche buono a sapersi, se stai solo cercando una stringa fissa e non una regex, usa l'opzione -F. ti farà risparmiare un sacco di tempo non invocando il regex parser. molto utile se stai cercando molti file.
Jeff,

6
alias rgrep = 'grep -r'
ottenuto il

679

Se conosci l'estensione o il modello del file che desideri, un altro metodo è utilizzare l' --includeopzione:

grep -r --include "*.txt" texthere .

Puoi anche menzionare i file da escludere --exclude.

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, è ricorsivo per impostazione predefinita e ignora automaticamente i file e le directory elencati .gitignore, quindi non è necessario continuare a passare le stesse ingombranti opzioni di esclusione per grep o find.


3
Funziona alla grande con grep fornito con Linux e Cygwin, ma non con quello fornito con AIX.
Sospeso il

1
@KrzysztofWolny: `` invece di =funzionare perfettamente su Ubuntu. PS: dovrebbe essere uno spazio con backtick, ma il parser SO markdown non è riuscito.
Dan Dascalescu,

4
@DanDascalescu Ho votato per il grep, non per l'Ag, solo per quello che sai :)
Bernhard

1
Abbiamo un'opzione per escludere una directory durante la ricerca ricorsiva?
Tom Taylor,

A Cygwin Windows piacciono le doppie virgolette--include "*.txt" --include "*.TXT"
Bob Stein,

127

Anche:

find ./ -type f -print0 | xargs -0 grep "foo"

ma grep -rè una risposta migliore.


14
O se non vuoi preoccuparti degli spazi nei nomi dei file find . -type f -exec grep "foo" '{}' \;funziona bene dove supportato.
Edd Steel,

4
Se stai per trovare pipe attraverso xargs per grep, E se stai solo cercando una stringa fissa (cioè non una regex), potresti trarre vantaggio dall'invocare l'opzione grep -F, quindi grep non caricherà il motore regex per ogni invocazione. Se ci sono molti file, sarà molto più veloce.
Jeff,

2
trova . -type f -exec grep -Hu "foo" {} \; è quello che uso in quanto fornisce il nome file.
Wes,

Funziona su tutti * nix perché è POSIX 7
Ciro Santilli 16 冠状 病 六四 事件 法轮功

1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke,

118

Ora uso sempre (anche su Windows con GoW - Gnu su Windows ):

grep --include="*.xxx" -nRHI "my Text to grep" *

Ciò include le seguenti opzioni:

--include=PATTERN

Recurse nelle directory cercando solo la corrispondenza dei file PATTERN.

-n, --line-number

Prefisso ogni riga di output con il numero di riga all'interno del suo file di input.

(Nota: phuclv aggiunge nei commenti che -ndiminuiscono molto le prestazioni , quindi potresti voler saltare quell'opzione )

-R, -r, --recursive

Leggi tutti i file in ciascuna directory, in modo ricorsivo; questo equivale -d recurseall'opzione.

-H, --with-filename

Stampa il nome file per ogni corrispondenza.

-I     

Elabora un file binario come se non contenesse dati corrispondenti;
questo equivale --binary-files=without-matchall'opzione.

E posso aggiungere ' i' ( -nRHIi), se voglio risultati senza distinzione tra maiuscole e minuscole.

Posso ottenere:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow sembra promettente, più recente delle utility Windows GNU che ho usato. Provandolo ora ...
Radim Cernej,

qual è il significato dell'ultimo carattere * qui?
lorniper,

2
@lorniper fa in modo che la shell selezioni tutti i file e le cartelle nella directory corrente, rendendo a sua volta il grep applicabile a quei file e (ricorsivamente a causa -Rdell'opzione) alle cartelle.
VonC

2
@lorniper Noy esattamente: *o .è un modello glob (interpretato dalla shell): unix.stackexchange.com/a/64695/7490 . ' .' selezionerà anche dotfile o dot folder (come .git/)
VonC

in precedenza l'ho sempre usato, grep -rnIma poi ho imparato che -ndiminuisce molto le prestazioni, quindi lo uso solo quando è veramente necessario e normalmente lo userò-rI
phuclv,

25

Nei sistemi POSIX, non trovi i -rparametri per grepe grep -rn "stuff" .non funzionerai, ma se usi il findcomando:

find . -type f -exec grep -n "stuff" {} \; -print

Concordato da Solarise HP-UX.


qual è il significato di {} \; -print rispettivamente?
user1169587,

3
In -execopzione - simbolo {}è un riferimento al nome del file che attualmente trovata da findstrumento (che è quello di fare qualcosa con il nome del file che abbiamo trovato), anche -execl'opzione deve essere chiuso con ;il simbolo (a marchio porre fine dei comandi exec), ma perché questo è tutto in esecuzione in una shell quel simbolo dovrebbe essere sfuggito .. e infine l' -printopzione consente findallo strumento di stampare i nomi dei file trovati sullo schermo.
Torre del

19

globbing **

L'uso grep -rfunziona, ma può essere eccessivo, specialmente nelle cartelle di grandi dimensioni.

Per un utilizzo più pratico, ecco la sintassi che utilizza la sintassi globbing ( **):

grep "texthere" **/*.txt

che greps solo file specifici con pattern selezionato pattern. Funziona con shell supportate come Bash +4 o zsh .

Per attivare questa funzione, eseguire: shopt -s globstar.

Vedi anche: Come posso trovare tutti i file contenenti testo specifico su Linux?

git grep

Per i progetti sotto il controllo della versione di Git, utilizzare:

git grep "pattern"

che è molto più veloce.

ripgrep

Per progetti più grandi, lo strumento di grepping più veloce è quello ripgrepche greps i file in modo ricorsivo per impostazione predefinita:

rg "pattern" .

È costruito sulla base del motore regex di Rust che utilizza automi finiti, SIMD e ottimizzazioni letterali aggressive per rendere la ricerca molto veloce. Controlla qui l'analisi dettagliata .


3
Grazie per il suggerimento git grep - è molto utile e non lo sapevo!
Basya,

2
Grazie per il suggerimento ripgrep. È molto più veloce.
Cosa sarebbe bello il

11

Per trovare il nome di filescon pathricorsivamente contenente il particolare stringuso di sotto di comando per UNIX:

find . | xargs grep "searched-string"

per Linux:

grep -r "searched-string" .

trova un file sul UNIXserver

find . -type f -name file_name

trova un file sul server LINUX

find . -name file_name

11

anche solo i nomi dei file possono essere utili

grep -r -l "foo" .

10

Se desideri seguire solo le directory effettive e non i collegamenti simbolici,

grep -r "thingToBeFound" directory

Se vuoi seguire i collegamenti simbolici e le directory effettive (fai attenzione all'infinita ricorsione),

grep -R "thing to be found" directory

Dal momento che stai provando a ricorrere in greece in modo ricorsivo, potrebbero essere utili anche le seguenti opzioni:

-H: outputs the filename with the line

-n: outputs the line number in the file

Quindi, se si desidera trovare tutti i file contenenti Darth Vader nella directory corrente o in qualsiasi sottodirectory e acquisire il nome file e il numero di riga, ma non si desidera che la ricorsione segua i collegamenti simbolici, il comando sarebbe

grep -rnH "Darth Vader" .

Se vuoi trovare tutte le menzioni della parola cat nella directory

/home/adam/Desktop/TomAndJerry 

e sei attualmente nella directory

/home/adam/Desktop/WorldDominationPlot

e vuoi catturare il nome del file ma non il numero di riga di qualsiasi istanza della stringa "cats" e vuoi che la ricorsione segua i collegamenti simbolici se li trova, puoi eseguire uno dei seguenti

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

Fonte:

con "grep --help" in esecuzione

Una breve introduzione ai collegamenti simbolici, per chiunque legga questa risposta e confuso dal mio riferimento a loro: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Bella risposta. Gli switch extra (-rnh) sono molto utili, quindi grazie per averli suggeriti.
semtex41

8

ag è il mio modo preferito per farlo ora github.com/ggreer/the_silver_searcher . È praticamente la stessa cosa di Ack ma con qualche ottimizzazione in più.

Ecco un breve benchmark. Svuoto la cache prima di ogni test (vedi /ubuntu/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

Se stai cercando un contenuto specifico in tutti i file da una struttura di directory, puoi usarlo findpoiché è più chiaro cosa stai facendo:

find -type f -exec grep -l "texthere" {} +

Si noti che -l(downcase di L) mostra il nome del file che contiene il testo. Rimuovilo se invece desideri stampare la corrispondenza stessa. Oppure usa -Hper ottenere il file insieme alla corrispondenza. Tutti insieme, altre alternative sono:

find -type f -exec grep -Hn "texthere" {} +

Dove -nstampa il numero di riga.


2
Votato per essere l'unica findsoluzione sia per evitare l'uso xargse l'uso non necessari +anziché \;con -exec, evitando così tonnellate di lanci di processi non necessari. :-)
ShadowRanger il

6

Questo è quello che ha funzionato per il mio caso sulla mia macchina attuale (git bash su Windows 7):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

Dimentico sempre -print0 e -0 per i percorsi con spazi.

EDIT: il mio strumento preferito ora è invece ripgrep: https://github.com/BurntSushi/ripgrep/releases . È davvero veloce e ha impostazioni predefinite migliori (come ricorsivo per impostazione predefinita). Stesso esempio della mia risposta originale ma usando ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (periodo di preavviso alla fine)

(^ credito: https://stackoverflow.com/a/1987928/1438029 )


Una precisazione:

grep -r "texthere" /(grep ricorsivamente tutte le directory e le sottodirectory)

grep -r "texthere" .(grep ricorsivamente queste directory e sottodirectory)

grep ricorsivo

grep [options] PATTERN [FILE...]

[opzioni]

-R, -r, --recursive

Leggi tutti i file in ciascuna directory, in modo ricorsivo.

Ciò equivale all'opzione -d recurseo --directories=recurse.

http://linuxcommand.org/man_pages/grep1.html

aiuto grep

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

alternative

ack( http://beyondgrep.com/ )

ag( http://github.com/ggreer/the_silver_searcher )


4

Nel 2018, vuoi usare ripgrepo the-silver-searcherperché sono molto più veloci delle alternative.

Ecco una directory con 336 sottodirectory di primo livello:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

Su OSX, questo viene installato ripgrep: brew install ripgrep. Questo consente di installare silver-searcher: brew install the_silver_searcher.


La velocità è importante se devi farlo spesso, ma la maggior parte di noi si trova a farlo solo poche volte all'anno al massimo. L'installazione dell'ultimo spettrale juju tool du jour di terze parti è eccessiva e le soluzioni che non sono cambiate molto dal 1978 sono buone da sapere a prescindere.
Tripleee,

Trovo altamente plausibile che un programmatore cerchi il testo in un albero di origine solo più volte all'anno. Ma anche dal punto di vista dell'usabilità, rgha un vantaggio considerevole rispetto al mettere insieme un comando ricorsivo grep da zero. Usando rg: rg foo. L'utilizzo di strumenti unix: find . | xargs grep foo. E se uno qualsiasi dei tuoi file contiene un preventivo, devi usarlo find . -print0 | xargs -0 grep foo. Ricorderai che se lo usi qualche volta all'anno?
hughdbrown,

1
Stai dimenticando find . -type f -exec grep 'regex' {} +che è davvero facile ricordare se usi questi strumenti con regolarità. Ma probabilmente dovresti comunque eseguire ctagso etagssul tuo albero dei sorgenti se devi trovare roba frequentemente.
triplo

Sto usando ripgrep ed è fantastico. Ma Silver Searcher è fantastico per i programmatori. +1
Matt,

3

Nel mio server IBM AIX (versione del sistema operativo: AIX 5.2), utilizzare:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

questo stamperà il percorso / nome del file e il relativo numero di riga nel file come:

./inc/xxxx_x.h

2865: / ** Descrizione: stringYouWannaFind * /

comunque, funziona per me:)


3

Di seguito sono riportati i comandi per la ricerca Stringricorsiva su Unixe Linuxambiente.

per UNIXcomando è:

find . -name "string to be searched" -exec grep "text" "{}" \;

per Linuxcomando è:

grep -r "string to be searched" .

2

Per un elenco di flag disponibili:

grep --help 

Restituisce tutte le corrispondenze per il regexp texthere nella directory corrente, con il numero di riga corrispondente:

grep -rn "texthere" .

Restituisce tutte le corrispondenze per texthere , a partire dalla directory principale, con il numero di riga corrispondente e ignorando il caso:

grep -rni "texthere" /

bandiere utilizzate qui:

  • -r ricorsivo
  • -n stampare il numero di riga con l'output
  • -i ignora il caso

1

Immagino sia questo ciò che stai cercando di scrivere

grep myText $(find .)

e questo potrebbe essere qualcos'altro utile se vuoi trovare i file grep hit

grep myText $(find .) | cut -d : -f 1 | sort | uniq

È molto intuitivo: ad esempio: grep -i acc $ (trova. -Name "esecuzione *. *")
Yu Shen

1

Lancio dei miei due centesimi qui. Come già menzionato da altri, grep -r non funziona su tutte le piattaforme. Può sembrare sciocco ma uso sempre git.

git grep "texthere"

Anche se la directory non è in scena, la metto in scena e utilizzo git grep.


0

Si noti che una serie find . -type f | xargs grep whateverdi soluzioni verrà eseguita in errori "Elenco argomenti troppo lungo" quando sono presenti troppi file corrispondenti a find.

La scommessa migliore è grep -rma se non è disponibile, utilizzare find . -type f -exec grep -H whatever {} \;invece.


Eh? xargsè in particolare una soluzione alternativa al problema "Elenco argomenti troppo lungo".
Tripleee,

2
Bene, no - xargs è specifico per convertire una pipe di argomenti in un arglist, ma sì, è vero che gli xargs moderni se usati con -s e / o -L possono gestire arglisti molto lunghi rompendo in più invocazioni di comandi, ma non è configurato in questo modo per impostazione predefinita (e non era in nessuna delle risposte sopra). Ad esempio:find . -type f | xargs -L 100 grep whatever
m.thome

Quale piattaforma sarebbe su? POSIXxargs è standardizzato per avere questo comportamento pronto all'uso. "L' xargsutilità deve limitare la lunghezza della riga di comando in modo tale che quando viene invocata la riga di comando, l'argomento combinato e gli elenchi di ambienti ... non devono superare {ARG_MAX} -2048 byte."
tripleee,

Hm. Mentre i documenti gnu sono meno chiari di posix su questa base e non ho più accesso alla macchina che mi ha fatto fare questa affermazione, non posso confermare la mia interpretazione originale su nessuna implementazione corrente. Il grep ricorsivo è, ovviamente, ancora preferibile se disponibile, ma ci sono poche ragioni per evitare la ricetta di xargs (usa -H per il grep per evitare che l'invocazione finale di grep venga superata solo un singolo nome file, però).
m.thome

0

Solo per divertimento, una ricerca veloce e sporca di file * .txt se la risposta di @christangrant è troppo da scrivere :-)

grep -r texthere .|grep .txt


0

Ecco una funzione ricorsiva (testata leggermente con bash e sh) che attraversa tutte le sottocartelle di una determinata cartella ($ 1) e utilizza le grepricerche per una determinata stringa ($ 3) in determinati file ($ 2):

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

Eseguendolo e un esempio di output:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .

7
Questo non aggiunge molto ad altre risposte
Mel
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.