Come faccio a trovare i file nella directory corrente che non contengono la parola foo
(usando grep
)?
Come faccio a trovare i file nella directory corrente che non contengono la parola foo
(usando grep
)?
Risposte:
Se il tuo grep ha l' opzione -L
(o --files-without-match
):
$ grep -L "foo" *
GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git'
: ^)
-rL
invece di -L
abbinare le sottodirectory
grep -L 'foo' -- *
lo standard è che i comandi che richiedono opzioni lunghe usano --
per indicare che non ci sono più opzioni dopo questo punto.
Dai un'occhiata ack
. Fa .svn
automaticamente l' esclusione per te, ti dà espressioni regolari Perl ed è un semplice download di un singolo programma Perl.
L'equivalente di ciò che stai cercando dovrebbe essere, in ack
:
ack -L foo
Puoi farlo con grep da solo (senza trovare).
grep -riL "foo" .
Questa è la spiegazione dei parametri utilizzati su grep
-L, --files-without-match
each file processed.
-R, -r, --recursive
Recursively search subdirectories listed.
-i, --ignore-case
Perform case insensitive matching.
Se usi l
(maiuscolo) otterrai il contrario (file con corrispondenze)
-l, --files-with-matches
Only the names of files containing selected lines are written
Il seguente comando mi dà tutti i file che non contengono il modello foo
:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep 0
grep '0$'
corrisponderebbe anche ai file con multipli di 10 righe! È necessario grep ':0$'
al fine di verificare la presenza di un esplicito ': 0' alla fine della linea. Quindi otterrai solo file con zero righe corrispondenti.
Il seguente comando esclude la necessità che find trovi il filtro delle svn
cartelle usando un secondo grep
.
grep -rL "foo" ./* | grep -v "\.svn"
Avrai effettivamente bisogno di:
find . -not -ipath '.*svn*' -exec grep -H -E -o -c "foo" {} \; | grep :0\$
Problema
Ho bisogno di refactoring di un grande progetto che utilizza i .phtml
file per scrivere HTML usando il codice PHP in linea. Voglio usare invece i modelli Moustache . Voglio trovare eventuali .phtml
file che non contengano la stringa new Mustache
poiché devono ancora essere riscritte.
Soluzione
find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
Spiegazione
Prima dei tubi:
Trova
find .
Trova i file in modo ricorsivo, iniziando da questa directory
-iname '*.phtml'
Il nome file deve contenere .phtml
(non lo i
distingue tra maiuscole e minuscole)
-exec 'grep -H -E -o -c 'new Mustache' {}'
Esegui il grep
comando su ciascuno dei percorsi corrispondenti
grep
-H
Stampa sempre le intestazioni del nome file con le righe di output.
-E
Interpreta il pattern come un'espressione regolare estesa (ovvero forza grep a comportarsi come egrep).
-o
Stampa solo la parte corrispondente delle linee.
-c
Solo un conteggio delle righe selezionate viene scritto nell'output standard.
Questo mi darà un elenco di tutti i percorsi dei file che finiscono .phtml
, con un conteggio del numero di volte in cui la stringa si new Mustache
verifica in ciascuno di essi.
$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
La prima pipe grep :0$
filtra questo elenco per includere solo le righe che terminano in :0
:
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0
La seconda pipe sed 's/..$//'
rimuove gli ultimi due caratteri di ogni riga, lasciando solo i percorsi dei file.
$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'
./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml
Il mio grep non ha alcuna opzione -L. Trovo soluzioni alternative per raggiungere questo obiettivo.
Le idee sono:
fare la differenza tra il file di dump 2 con il comando diff.
grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
grep * *.log | cut -c1-14 | uniq > txt2.txt
diff txt1.txt txt2.txt | grep ">"
diff
tra due flussi di output (penso che tu circonda i comandi tra parentesi e c'è anche una parentesi angolare da qualche parte), se i tuoi sistemi lo supportano, che immagino è la domanda, poiché non supportagrep -L
find *20161109* -mtime -2|grep -vwE "(TRIGGER)"
È possibile specificare il filtro in "trova" e la stringa di esclusione in "grep -vwE". Usa mtime sotto find se hai bisogno di filtrare anche sul tempo modificato.
Come commentato da @tukan, esiste una segnalazione di bug aperta per Ag riguardante il flag -L
/ --files-without-matches
:
Poiché la segnalazione del bug presenta pochi progressi, l' -L
opzione menzionata di seguito non deve essere considerata attendibile , non finché il bug non è stato risolto. Utilizzare invece approcci diversi presentati in questo thread. Citando un commento per la segnalazione di bug [mio accento]:
Qualche aggiornamento su questo?
-L
ignora completamente le corrispondenze sulla prima riga del file. Sembra che se questo non verrà risolto presto, la bandiera dovrebbe essere rimossa del tutto, poiché effettivamente non funziona come pubblicizzato .
Come potente alternativa a grep
, è possibile utilizzare The Silver Searcher - Ag :
Uno strumento di ricerca del codice simile a ack, con un focus sulla velocità.
Guardando man ag
, troviamo l' opzione -L
o --files-without-matches
:
... OPTIONS ... -L --files-without-matches Only print the names of files that don´t contain matches.
Vale a dire, per cercare ricorsivamente file che non corrispondono foo
, dalla directory corrente:
ag -L foo
Per cercare solo nella directory corrente i file che non corrispondono foo
, basta specificare --depth=0
per la ricorsione:
ag -L foo --depth 0
-L
bug - github.com/ggreer/the_silver_searcher/issues/238
grep -irnw "filepath" -ve "pattern"
o
grep -ve "pattern" < file
sopra il comando ci darà il risultato come -v trova l'inverso del pattern cercato
-l
opzione per stampare solo il nome del file; ma ciò stampa ancora i nomi di qualsiasi file che contiene una riga che non contiene il modello. Credo che l'OP voglia trovare i file che non contengono alcuna riga che contiene il modello.
Il seguente comando potrebbe aiutarti a filtrare le linee che includono la sottostringa "pippo".
cat file | grep -v "foo"
cat
.