linux - solo - Come si esegue il grep in modo ricorsivo?




grep solo prima occorrenza (16)

Come faccio a ricorsivamente grep tutte le directory e sottodirectory?

find . | xargs grep "texthere" *

globbing **

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

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

grep "texthere" **/*.txt

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

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

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

git grep

Per i progetti con controllo di versione Git, utilizzare:

git grep "pattern"

che è molto più veloce.

ripgrep

Per i progetti più grandi, lo strumento di grepping più veloce è ripgrep che greps i file in modo ricorsivo di default:

rg "pattern" .

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


Anche:

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

ma grep -r è una risposta migliore.


Ecco una funzione ricorsiva (testata alla leggera con bash e sh) che attraversa tutte le sottocartelle di una determinata cartella ($ 1) e utilizza le ricerche di grep 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

Immagino che questo sia quello 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

Nel 2018, vuoi usare ripgrep o the-silver-searcher perché 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, installa ripgrep : brew install ripgrep . Questo installa silver-searcher : brew install the_silver_searcher .


Nel mio IBM AIX Server (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:)


Oppure installa ack, se vuoi un modo molto più veloce e lo stai facendo molto.


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 solo alla ricerca di file corrispondenti a PATTERN .

-n, --line-number

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

-R, -r, --recursive

Leggi tutti i file sotto ogni directory, in modo ricorsivo; questo è equivalente all'opzione -d recurse .

-H, --with-filename

Stampa il nome del file per ogni partita.

-I     

Elabora un file binario come se non contenga dati corrispondenti;
questo è equivalente --binary-files=without-match .

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

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 , iniziando dalla directory principale, con il numero di riga corrispondente e ignorando il caso:

grep -rni "texthere" /

bandiere usate qui:

  • -r ricorsivo
  • -n numero di riga di stampa con uscita
  • -i ignoro il caso

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

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

Ho sempre dimenticato -print0 e -0 per i percorsi con spazi.

EDIT: il mio strumento preferito ora è ripgrep: https://github.com/BurntSushi/ripgrep/releases . È molto veloce e ha valori predefiniti migliori (come ricorsivo di default). Stesso esempio della mia risposta originale ma usando ripgrep: rg -g "*.cs" "content pattern"


Se conosci l'estensione o il pattern del file che desideri, un altro metodo è usare l'opzione --include :

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

Puoi anche menzionare i file da escludere con --exclude .

Ag

Se cerchi spesso il codice, github.com/ggreer/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 in .gitignore , quindi non è necessario continuare a passare le stesse opzioni di esclusione ingombranti a grep o find.


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

grep -r "thingToBeFound" directory

Se si desidera seguire i collegamenti simbolici e le directory effettive (fare attenzione alla ricorsione infinita),

grep -R "thing to be found" directory

Poiché stai provando a grep in modo ricorsivo, le seguenti opzioni potrebbero essere utili anche a te:

-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 tu 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 "gatti" e vuoi che la ricorsione segua i link simbolici se li trova, potresti eseguire uno dei seguenti

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

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

Fonte:

in esecuzione "grep - help"

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


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

grep -r texthere .|grep .txt


ag è il mio modo preferito per farlo ora github.com/ggreer/the_silver_searcher . È fondamentalmente la stessa cosa dell'ack, ma con qualche altra ottimizzazione.

Ecco un breve punto di riferimento. Svuoto la cache prima di ogni test (cf https://askubuntu.com/questions/155768/how-do-i-clean-or-disable-the-memory-cache )

[email protected]$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
[email protected]$ time grep -r "hey ya" .

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

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

real    0m5.641s
user    0m0.356s
sys 0m3.444s
[email protected]$ time ag "hey ya" . #test without first clearing cache

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

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

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

Una precisazione:

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

grep -r "texthere" . (ricristiano in modo ricorsivo queste directory e sottodirectory)

grep ricorsivo

grep [options] PATTERN [FILE...]

[opzioni]

-R, -r, --recursive

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

Questo è equivalente alla opzione -d recurse --directories=recurse o --directories=recurse .

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

aiuto di grep

$ grep --help

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

alternative

ack ( ack )

ag ( github.com/ggreer/the_silver_searcher )


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




grep