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

È stato utile?

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="

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 d'ambiente: GREP_OPTIONS = " - exclude-dir = .svn "

Secondo Andy voterò per ack , tuttavia, è il migliore.

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 grep

Prova 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:

  1. Crea una cartella denominata " --F " sotto currdir .. (o collega un'altra cartella lì rinominata in " --F " ovvero double-minus-F .
  2. # > grep -i --exclude-dir = " \ - \ - F " & Quot; modello " *
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top