Usa grep --exclude / - include la sintassi per non grep attraverso determinati file
-
03-07-2019 - |
Domanda
Sto cercando la stringa foo =
nei file di testo in un albero di directory. È su una macchina Linux comune, ho bash shell:
grep -ircl "foo=" *
Nelle directory ci sono anche molti file binari che corrispondono a " foo = " ;. Poiché questi risultati non sono pertinenti e rallentano la ricerca, voglio che grep salti la ricerca di questi file (principalmente immagini JPEG e PNG). Come lo farei?
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.
La ricerca su grep include , grep include exclude , grep exclude e le varianti non hanno trovato nulla di pertinente
Se esiste un modo migliore di eseguire il grepping solo in determinati file, sono pronto per questo; spostare i file offensivi non è un'opzione. Non riesco a cercare solo determinate directory (la struttura delle directory è un gran casino, con tutto ovunque). Inoltre, non posso installare nulla, quindi ho a che fare con strumenti comuni (come grep o il suggerito trova ).
Soluzione
Usa la sintassi globbing della shell:
grep pattern -r --include=\*.{cpp,h} rootdir
La sintassi per --exclude
è identica.
Nota che la stella è sfuggita a una barra rovesciata per evitare che venga espansa dalla shell (citandola, come --include = " *. {cpp, h} "
, funzionerebbe altrettanto bene). Altrimenti, se nella directory di lavoro corrente fossero presenti file corrispondenti al modello, la riga di comando si espanderebbe in qualcosa come grep pattern -r --include = foo.cpp --include = bar.h rootdir
, che cerca solo i file denominati foo.cpp
e bar.h
, che probabilmente non è quello che volevi.
Altri suggerimenti
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 ricorsivamente, ignora i file binari e non cerca all'interno delle cartelle nascoste di Subversion, qualunque sia il modello che voglio. L'ho aliasato come "grepsvn" sulla mia scatola al lavoro.
Dai un'occhiata a ack , progettato proprio per queste situazioni. Il tuo esempio di
grep -ircl --exclude=*.{png,jpg} "foo=" *
viene eseguito con ack as
ack -icl "foo="
perché ack non cerca mai nei file binari per impostazione predefinita e -r è attivo per impostazione predefinita. E se vuoi solo file CPP e H, fai semplicemente
ack -icl --cpp "foo="
L'ho trovato dopo molto tempo, puoi aggiungere più inclusioni ed esclusioni 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 nome di base. In altre parole, salterà solo il .svn nella directory corrente.
In grep 2.5.1 devi aggiungere questa linea al profilo ~ / .bashrc o ~ / .bash
export GREP_OPTIONS="--exclude=\*.svn\*"
Trovo che l'output di grep grepping sia molto utile a volte:
grep -rn "foo=" . | grep -v "Binary file"
Tuttavia, ciò non gli 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*"
Nota la mancanza di segni di uguale " = " (altrimenti --include
, --exclude
, include-dir
e --exclude-dir
vengono ignorati)
Se non sei contrario all'utilizzo di find
, mi piace la sua funzione -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
Nella prima riga, si specifica la directory che si desidera cercare. .
(directory corrente) è un percorso valido, ad esempio.
Sulla 2a e 3a riga, usa " *. png "
, " *. gif "
, " *. jpg " e così via. Usa quanti di questi
-o -name " ... " -prune
costruisce come hai i modelli.
Sulla quarta riga, hai bisogno di un altro -o
(specifica " o " per find
), i pattern che vuoi, e hai bisogno di un < code> -print o -print0
alla fine. Se desideri semplicemente " tutto il resto " che rimane dopo aver eliminato le immagini * .gif
, * .png
, ecc., quindi utilizzare
-o -print0
e hai finito con la 4a riga.
Infine, sulla quinta riga c'è la pipe per xargs
che prende ciascuno di quei file risultanti e li memorizza in una variabile FILENAME
. Quindi passa grep
i flag -IR
, il " pattern "
, e quindi FILENAME
viene espanso di < code> xargs per diventare quell'elenco di nomi file trovati da find
.
Per la tua domanda particolare, l'affermazione potrebbe essere simile a:
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, ho dovuto usare --exclude-dir due volte.
git grep
Usa git grep
che è ottimizzato per le prestazioni e mira a cercare determinati file.
Di default ignora i file binari e onora il tuo .gitignore
. Se non lavori con la struttura Git, puoi comunque usarla passando --no-index
.
Sintassi di esempio:
git grep --no-index "some_pattern"
Per altri esempi, vedi:
Prova questo:
$ find . -name "*.txt" -type f -print | xargs file | grep "foo=" | cut -d: -f1
Trovato qui: http: //www.unix.com/shell-programming-scripting/42573-search-files-excluding-binary-files.html
Se esegui una ricerca in modo non ricorsivo, puoi utilizzare glop pattern 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 directory secondarie:
grep "foo" */*/*.{html,txt}
find e xargs sono i tuoi amici. Usali per filtrare l'elenco dei file piuttosto che --exclude
di grepProva qualcosa del genere
find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
quegli script non risolvono tutto il problema ... Prova meglio:
du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"
questo script è molto meglio, perché usa " real " espressioni regolari per evitare la ricerca di directory. basta separare i nomi di cartelle o file con " \ | " sul grep -v
divertiti! trovato sulla mia shell Linux! XD
Guarda @ questo.
grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
Nelle directory ci sono anche molti file binari. Non riesco a cercare solo determinate directory (la struttura delle directory è un gran casino). Esiste un modo migliore per eseguire il grepping solo in determinati file?
ripgrep
Questo è uno degli strumenti più veloci progettati per eseguire ricerche ricorsive nella directory corrente. È scritto in Rust , costruito sopra motore regex di Rust per la massima efficienza. Controlla la analisi dettagliata qui .
Quindi puoi semplicemente eseguire:
rg "some_pattern"
Rispetta il tuo .gitignore
e salta automaticamente file / directory nascosti e file binari.
Puoi comunque personalizzare includere o escludere file e directory usando -g
/ --glob
. Le regole globbing corrispondono ai globs .gitignore
. Controlla man rg
per aiuto.
Per altri esempi, vedi: Come escludere alcuni file che non corrispondono a determinate estensioni con grep?
Su macOS, puoi installare tramite brew install ripgrep
.
L'opzione --binary-files = without-match
su GNU grep
consente di saltare i file binari. (Equivalente all'opzione -I
menzionata altrove.)
(Questo potrebbe richiedere una versione recente di grep
; almeno 2.5.3 ce l'ha).
adatto per il file tcsh .alias:
alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'
Mi ci è voluto un po 'per capire che la parte {mm, m, h, cc, c} NON dovrebbe essere tra virgolette. ~ Keith
Per ignorare tutti i risultati binari di grep
grep -Ri "pattern" * | awk '{if($1 != "Binary") print <*>}'
La parte awk filtra tutti i file binari che corrispondono alle linee
Prova questo:
- Crea una cartella denominata "
--F
" sotto currdir .. (o collega un'altra cartella lì rinominata in "--F
" ovverodouble-minus-F
. -
# > grep -i --exclude-dir = " \ - \ - F " & Quot; modello " *