Domanda Come usare il comando "grep" per trovare il testo incluse le sottodirectory


Voglio trovare tutti i file che contengono una stringa di testo specifica. Il grep il comando funziona, ma non so come usarlo per ogni directory (posso farlo solo per la mia directory corrente). Ho provato a leggere man grep, ma non ha dato alcun aiuto.


292
2017-08-01 11:38


origine


grep -RIn <yor pattern> * Effettua la ricerca dalle directory correnti verso il basso in tutti i file di testo. Non so come fare la mia ricerca in modo ricorsivo in modelli di file come * .C con solo grep
Wildcard con --include="*.C" opzione, @ user311346, grazie a @Lekensteyn. - Bob Stein
Utilizzare la combinazione find e grep per cercare ricorsivamente i file per una stringa nelle directory correnti e in tutte le sottodirectory. Controllare questo wilddiary.com/find-files-containing-my-text - Drona


risposte:


Sarebbe meglio da usare

grep -rl "string" /path

dove

  • -r (o --recursive) opzione viene utilizzata per attraversare anche tutte le sottodirectory di /path, mentre
  • -l (o --files-with-matches) opzione viene utilizzata per stampare solo i nomi dei file corrispondenti, e non le linee corrispondenti (questo potrebbe anche migliorare la velocità, dato che grep smettere di leggere un file alla prima corrispondenza con questa opzione).

375
2017-08-01 11:55



In realtà se "string" è un pattern di testo da trovare, è meglio usare quella funzionalità, altrimenti qualcuno può affrontare problemi quando la stringa contiene punti o caratteri speciali che hanno un significato nelle espressioni regolari e non solo un punto che dovrebbe essere trovato come una stringa , come è. Quindi vorrei usare -rlF interruttori, -F per "stringa fissa" (e non regexp - per esempio). Certo, se l'attività utilizzava espressioni regolari, allora mi scusi. Certo, la stessa teoria senza -r anche io, spesso vedo che la gente assume le ricerche di grep "testo" e può causare problemi a quelli speciali che significano qualcosa come una regexp. - LGB
C'è anche il -i bandiera che ignora il caso. - Marco Ceppi♦
Vorrei solo mostrare il --recursive opzione, ci sono un sacco di opzioni e scenari di utilizzo di cui si può parlare. Ho iniziato dalla risposta accettata da @dmityugov e modificato per funzionare senza find. - enzotib
@ N.N .: fatto :-) - enzotib
@ScottBiggs: con l'opzione --include '*.h' - enzotib


Se cerchi le linee che corrispondono ai file, il mio comando preferito è:

grep -Hrn 'search term' path/to/files
  • -H causa la stampa del nome del file (implicito quando vengono cercati più file)
  • -r fa una ricerca ricorsiva
  • -n causa la stampa del numero di riga

path/to/files può essere . per cercare nella directory corrente

Ulteriori opzioni che trovo molto utili:

  • -I ignora i file binari (complemento: -a tratta tutti i file come testo)
  • -F trattare search term come un'espressione letterale, non regolare
  • -i fare una ricerca insensibile alle maiuscole e minuscole
  • --color=always per forzare i colori anche quando convogliano less. Fare less colori di supporto, è necessario utilizzare il -r opzione:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dir utile per escludere directory come .svn e .git.

Example output


136
2017-08-01 12:27



-H su una cartella è ridondante, se c'è più di un file, come è probabile. In effetti, la pagina man dice -H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search. - enzotib
Non lo sapevo, funzionava sempre come mi aspettavo. È il mio comando predefinito durante la ricerca di file. - Lekensteyn
C'è un modo per considerare solo i file con estensione, ad esempio .a (e combinarli con -r)? - user2413
@ utente2413 Prova --include '*.*' - Lekensteyn
@enzotib Solo una FYI: non ottengo l'output pulito di ogni riga in ogni file in cui il mio testo appare con -rln o -rl, ma lo faccio con -Hrn. Ridondante o no, sembra lo screenshot in alto con le opzioni -Hrn. Inoltre, non sembra che -n funzioni senza -H. - SgtPooki


Credo che tu possa usare qualcosa del genere:

find /path -type f -exec grep -l "string" {} \;

Spiegazione dai commenti

find è un comando che ti consente di trovare file e altri oggetti come directory e collegamenti nelle sottodirectory di un determinato percorso. Se non si specifica una maschera che i nomi dei file devono soddisfare, enumera tutti gli oggetti directory.

  • -type f specifica che dovrebbe elaborare solo i file, non le directory, ecc.
  • -exec grep specifica che per ogni file trovato, dovrebbe eseguire il comando grep, passando il suo nomefile come argomento ad esso, sostituendolo {} con il nome del file

21
2017-08-01 11:48



Solo per quelli che non sanno, aggiungendo -name '*.py' limita le corrispondenze ai file che terminano in ".py". - Daniel F
Mi piace che questo copra i client che non hanno implementato -R nel loro comando grep. - Aviose


Il mio comando predefinito è

grep -Rin string *

Io uso un capitol 'R' perché ls lo usa per ricorsivo. Dal momento che grep accetta entrambi, non c'è motivo di non usarlo.

EDIT: a HVNSweeting, apparentemente -R seguirà i link simbolici dove -r non lo farò.


17
2017-08-01 14:43



Per cercare anche nei file nascosti, esegui shopt -s dotglob (ricorda -s bene"). Fai attenzione quando rimuovi i file. Se hai dotglob abilitato, rm -r * rimuove tutto nella directory corrente, ma anchela directory sopra perché .. le partite. Per disabilitare dotglob, usare shopt -u dotglob ( "Unset"). Le modifiche sono tuttavia temporanee, si applica solo alla shell corrente. - Lekensteyn
Mi sono dimenticato di questo. C'è un modo per impostarlo per una sola riga? qualcosa di simile a shopt -s dotglob & <grep cmd> & shopt -y dotglob solo più conveniente? In questo modo non dovremo preoccuparci di resettarlo - user606723
Inoltre, probabilmente è più facile da usare grep -Rin string . nella maggior parte di questi casi. Uso solo * perché sembra venire più naturale. - user606723
se fai grep ricorsivo, puoi iniziare da "." invece di "*". non è necessario dotglob. - Michał Šrajer
votare su questo, una cosa non cita in manpage è R seguirà collegamenti simbolici, r non - HVNSweeting


Se sei disposto a provare qualcosa di nuovo, dai ack un colpo. Il comando per cercare ricorsivamente la directory corrente string è:

ack string

L'installazione è abbastanza semplice:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(A condizione che tu abbia già la directory ~/bin ed è preferibilmente nel tuo PATH.)


11
2017-08-01 15:09



O semplicemente apt-get install ack-grep (, e aggiungi alias ack = ack-grep al tuo .bashrc) - markijbema
Cosa fanno gli ultimi parametri al chmod comando? Sono specifici per chmod o sono legati bash (il !#:3 parte)? - Elliott Darfink
@ElliottDarfink Questo sta usando Bash's caratteristica della storia - ! è un designatore di eventi. Sono piuttosto potenti per evitare le ripetizioni. !#:3 fa riferimento al terzo token della riga di comando fino ad ora, ad es. ~/bin/ack in questo caso. - Konrad Rudolph


Il comando rgrep è dedicato a tale necessità

Se non disponibile, puoi farlo in questo modo

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

È possibile impostare direttamente le opzioni di grep predefinite come descritto sopra.

Io uso personalmente

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

argomento correlato: come usare sempre rgrep con il colore


3
2018-01-02 13:58



rgrep è fornito dal pacchetto grep che viene installato di default in Ubuntu. - karel


Aggiornamento 2:

Questa linea di comandi utilizza find e grep risolve il problema:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> per uscita colorata:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Esempio:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Un esempio di esecuzione nello snapshot di seguito: snap1


Aggiornamento 1:

Puoi provare il seguente codice; come una funzione nel tuo .bashrco .bash_aliases o in una sceneggiatura:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Uso: wherein /path/to/search/in/ searchkeyword

esempio:

$ wherein ~/Documents/ "hello world"

(Nota: come suggerito nei commenti sotto di @enzotib, questo non funziona con file / directory inclusi spazi nei loro nomi).


Post originale

Per cercare la stringa ed emettere solo quella riga con la stringa di ricerca:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

per esempio.:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Per visualizzare il nome del file contenente la stringa di ricerca:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

per esempio.:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

2
2018-01-25 11:11



Errore nei nomi di file contenenti spazi. Il fallimento è nascosto dal fatto che stderr non viene mostrato. - enzotib
@enzotib grazie per averlo indicato ... che è ancora irrisolto per la funzione specificata .. Ho aggiunto un altro one-liner però .. - precise
Ora la risposta è simile a quella di @dmityugov. - enzotib
si, ma in questo senso la maggior parte delle risposte in questa pagina se si controlla sono simili rispetto a quelle che usano grep, accanto a quello è il sottoinsieme che usa find con grep... ma se devi accettare interruttori e ritocchi diversi come risposta distinta, probabilmente anche il mio si adatterà a questo. O sei diverso? l'ultimo aggiornamento fa quello che mi piacerebbe nella mia ricerca: nomi di file con linee con chiave di ricerca e riga n. too :) e uscita colorata e filtro di errore per una migliore leggibilità .. - precise


Lo faccio usando xargs, un comando molto sottovalutato

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ fornisce un elenco ricorsivo di tutti i file in una cartella corrente quindi lo conduci su xargs che esegue il comando grep su ognuno di quei file


1
2017-08-01 15:30



utilizzando xargs senza -print0 opzione a find e -0 opzione a xargs è deprecato, fallirà sui nomi di file che contengono spazi. - enzotib
@enzotib Ho modificato la risposta come mi hai suggerito.- ti preghiamo di rivedere e se è necessario apportare modifiche e correzioni, sarò lieta di ri-montare da te. grazie - αғsнιη
@KasiyA: è ok ora, rimosso il mio downvote. - enzotib