risposta-alla-domanda-sullo-sviluppo-web-bd.com

Utilizza grep --exclude/- include sintassi per non eseguire il grep con determinati file

Sto cercando la stringa foo= nei file di testo in un albero di directory. È su una macchina Linux comune, ho una shell bash:

grep -ircl "foo=" *

Nelle directory ci sono anche molti file binari che corrispondono a "foo =". Poiché questi risultati non sono rilevanti e rallentano la ricerca, voglio grep per saltare la ricerca di questi file (principalmente immagini JPEG e PNG). Come potrei farlo?

So che ci sono le opzioni --exclude=PATTERN e --include=PATTERN, ma qual è il formato del pattern? La pagina man di grep dice:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Ricerca su grep include , grep include exclude , grep exclude e le varianti non hanno trovato nulla di rilevante

Se c'è un modo migliore di fare il grepping solo in certi file, sono tutto per lui; spostare i file incriminati non è un'opzione. Non riesco a cercare solo certe directory (la struttura delle directory è un bel casino, con tutto ovunque). Inoltre, non posso installare nulla, quindi ho a che fare con strumenti comuni (come grep o il suggerito find ).

719
Piskvor

Usa la sintassi globbing della shell:

grep pattern -r --include=\*.{cpp,h} rootdir

La sintassi per --exclude è identica.

Si noti che la stella è sfuggita con una barra rovesciata per impedire che venga espansa da Shell (citandola, come --include="*.{cpp,h}", funzionerebbe altrettanto bene). Altrimenti, se nella directory di lavoro corrente sono presenti file corrispondenti al pattern, la riga di comando si espanderebbe in qualcosa come grep pattern -r --include=foo.cpp --include=bar.h rootdir, che cercherebbe solo i file foo.cpp e bar.h, che probabilmente non è quello che volevi.

689
Adam Rosenfield

Se vuoi solo saltare i file binari, ti suggerisco di guardare l'opzione -I (maiuscolo i). Ignora i file binari. Uso regolarmente il seguente comando:

grep -rI --exclude-dir="\.svn" "pattern" *

Cerca in modo ricorsivo, ignora i file binari e non guarda all'interno delle cartelle nascoste di Subversion, per qualunque modello io voglia. Ho alias come "grepsvn" sulla mia scatola al lavoro.

211
rmeador

Si prega di dare un'occhiata a ack , che è stato progettato proprio per queste situazioni. Il tuo esempio di

grep -ircl --exclude=*.{png,jpg} "foo=" *

è fatto con ack come

ack -icl "foo="

perché Ack non guarda mai nei file binari per impostazione predefinita e -r è attivo per impostazione predefinita. E se vuoi solo i file CPP e H, allora basta

ack -icl --cpp "foo="
61
Andy Lester

grep 2.5.3 ha introdotto il parametro --exclude-dir che funzionerà nel modo desiderato.

grep -rI --exclude-dir=\.svn PATTERN .

Puoi anche impostare una variabile di ambiente: GREP_OPTIONS = "- exclude-dir = .svn"

Seguirò Andy's voterò per ack sebbene, sia il migliore.

34
Corey

Ho trovato questo dopo molto tempo, è possibile aggiungere più include ed esclude come:

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
24
Rushabh Mehta

Il comando suggerito:

grep -Ir --exclude="*\.svn*" "pattern" *

è concettualmente sbagliato, perché --exclude funziona sul basename. In altre parole, salterà solo il .svn nella directory corrente.

12
Nicola

In grep 2.5.1 devi aggiungere questa linea a ~/.bashrc o ~/.bash profile

export GREP_OPTIONS="--exclude=\*.svn\*"
11
deric

Trovo che l'output di grep di grep sia molto utile a volte:

grep -rn "foo=" . | grep -v "Binary file"

Tuttavia, questo in realtà non impedisce di cercare i file binari.

9
Aaron Maenpaa

Su CentOS 6.6/Grep 2.6.3, devo usarlo in questo modo:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

Notare la mancanza di segni di uguale "=" (altrimenti --include, --exclude, include-dir e --exclude-dir sono ignorati)

7
aesede

Se non sei contrario all'uso di find, mi piace la sua caratteristica -Prune:


find [directory] \
        -name "pattern_to_exclude" -Prune \
     -o -name "another_pattern_to_exclude" -Prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

Sulla prima riga, si specifica la directory che si desidera cercare. . (directory corrente) è un percorso valido, ad esempio.

Sulla seconda e terza riga, utilizzare "*.png", "*.gif", "*.jpg" e così via. Usa tanti di questi costrutti -o -name "..." -Prune come hai schemi.

Sulla quarta riga, hai bisogno di un altro -o (specifica "o" per find), i pattern che vuoi e hai bisogno di un -print o -print0 alla fine di esso. Se vuoi solo "tutto il resto" che rimane dopo aver potato le immagini *.gif, *.png, ecc., Usa -o -print0 e hai finito con la 4a linea.

Infine, sulla quinta riga c'è la pipe a xargs che prende ciascuno di quei file risultanti e li memorizza in una variabile FILENAME. Quindi passa grep i flag -IR, "pattern", e quindi FILENAME è espanso da xargs per diventare l'elenco di nomi di file trovati da find.

Per la tua domanda particolare, la dichiarazione può sembrare qualcosa di simile:


find . \
     -name "*.png" -Prune \
     -o -name "*.gif" -Prune \
     -o -name "*.svn" -Prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES
6
OnlineCop

Sono un dilettante, garantito, ma ecco come appare il mio ~/.bash_profile:

 export GREP_OPTIONS = "- orl --exclude-dir = .svn --exclude-dir = .cache --color = auto" GREP_COLOR = '1; 32' 

Nota che per escludere due directory, dovevo usare --exclude-dir due volte.

5
4D4M

git grep

Usa git grep che è ottimizzato per le prestazioni e mira a cercare tra determinati file.

Di default ignora i file binari e rende onore al tuo .gitignore. Se non stai lavorando con la struttura di Git, puoi ancora usarlo passando --no-index.

Sintassi di esempio:

git grep --no-index "some_pattern"

Per ulteriori esempi, vedi:

4
kenorb

Prova questo:

 $ trovare. -name "* .txt" -tipo f -print | file xargs | grep "foo =" | cut -d: -f1 

Fondato qui: http://www.unix.com/Shell-programming-scripting/42573-search-files-excluding-binary-files.html

3
Gravstar

Se cerchi in modo non ricorsivo puoi usare glop patterns per abbinare i nomi dei file.

grep "foo" *.{html,txt}

include html e txt. Cerca solo nella directory corrente.

Per cercare nelle sottodirectory:

   grep "foo" */*.{html,txt}

Nelle sottodirectory:

   grep "foo" */*/*.{html,txt}
3

Guarda @ questo.

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
2
suhas tawade

quegli script non soddisfano tutti i problemi ... Provalo meglio:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

questo script è molto migliore, perché usa espressioni regolari "reali" per evitare le directory dalla ricerca. basta separare i nomi delle cartelle o dei file con "\ |" sulla grep -v

divertirsi! trovato sulla mia shell Linux! XD

2
villalvilla

Nelle directory ci sono anche molti file binari. Non riesco a cercare solo certe directory (la struttura delle directory è un grosso casino). C'è un modo migliore di grepping solo in determinati file?

ripgrep

Questo è uno degli strumenti più veloci progettati per cercare ricorsivamente la directory corrente. È scritto in Rust , costruito sopra Rust's regex engine per la massima efficienza. Controlla l'analisi dettagliata qui .

Quindi puoi semplicemente eseguire:

rg "some_pattern"

Rispetta il tuo .gitignore e salta automaticamente i file/directory e i file binari nascosti.

È comunque possibile personalizzare includere o escludere file e directory utilizzando -g/--glob. Le regole di Globbing corrispondono ai glob .gitignore. Controlla man rg per aiuto.

Per ulteriori esempi, vedi: Come escludere alcuni file che non corrispondono ad alcune estensioni con grep?

Su macOS, puoi installare tramite brew install ripgrep.

2
kenorb

find e xargs sono i tuoi amici. Usali per filtrare la lista dei file invece di grep --exclude

Prova qualcosa del genere

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
2
Andrew Stein

adatto per il file tcsh .alias:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

Ci ho messo un po 'a capire che la porzione {mm, m, h, cc, c} NON dovrebbe essere racchiusa tra virgolette. ~ Keith

1
Keith Knauber

L'opzione --binary-files=without-match per GNU grep consente di saltare i file binari. (Equivalente all'interruttore -I menzionato altrove).

(Questo potrebbe richiedere una versione recente di grep; 2.5.3 ce l'ha, almeno.)

1
mjs

Per ignorare tutti i risultati binari di grep

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

La parte di awk filtrerà tutte le righe del file binario foo

0
lathomas64