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 ).
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.
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.
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="
Ho trovato questo dopo molto tempo, è possibile aggiungere più include ed esclude come:
grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
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.
In grep 2.5.1 devi aggiungere questa linea a ~/.bashrc o ~/.bash profile
export GREP_OPTIONS="--exclude=\*.svn\*"
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.
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)
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
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.
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:
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
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}
Guarda @ questo.
grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
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
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
.
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="
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
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.)
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