Pipe trova in grep -v


18

Sto cercando di trovare tutti i file che sono di un certo tipo e non contengono una determinata stringa. Sto provando ad aggirare il problema, trovando grep -v

esempio:

find -type f -name '*.java' | xargs grep -v "something something"

Questo non sembra funzionare. Sembra che stia solo restituendo tutti i file trovati dal comando find. Quello che sto cercando di fare è fondamentalmente trovare tutti i file .java che corrispondono a un determinato nome di file (ad esempio, termina con "Pb" come in SessionPb.java) e che non contengono "extending SomethingSomething" al suo interno.

Il mio sospetto è che sto sbagliando. Quindi, come dovrebbe essere invece il comando?


potresti aggiungere ciò che ti fa pensare che non abbia funzionato. forse la tua espressione grep è troppo esplicita? serve un '-i' per l'insensibilità ai casi? Vedi anche la mia risposta qui sotto ...
lornix il

Risposte:


21

Non è necessario xargsqui. Inoltre è necessario utilizzare grepcon l' -Lopzione (file senza corrispondenza), in caso contrario verrà generato il contenuto del file anziché il suo nome, come nel tuo esempio.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

1
-Lha già una negoziazione, perché significa files _without_ match. Pertanto non è necessaria l' -vopzione qui.
precipita il

3
non con l'aggiunta + alla fine.
lynxlynxlynx,

2
@ user946850 ogni volta che scrivo find -exec \+qualcuno mi scrive che è molto meglio usare xargs. perché nessuno guarda l'uomo prima di scrivere un commento? (:
precipita il

5
@ user946850 -exec ... {} \+non è equivalente a xargs. Si prega di leggere la documentazione di findutils! (Ci ho lavorato abbastanza!)
James Youngman,

2
@ user946850 sì. Una delle differenze è che (per impostazione predefinita) xargselabora il suo input e separa gli argomenti su uno spazio bianco. Le citazioni sono anche speciali (per impostazione predefinita) in xargs. Nessuna di queste cose è vera per -exec ... {} +. Le vecchie versioni di xargsusato consideravano il carattere di sottolineatura come un indicatore EOF, ma non è più così.
James Youngman,

7

Hai quasi capito davvero ...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

Il punto '.' dice di iniziare da qui. (il tuo lo implica .. ma non dare mai per scontato).

-iname utilizza la ricerca senza distinzione tra maiuscole e minuscole, per ogni evenienza (o semplicemente in nessun caso).
-print0 invia nomi di file a xargs con un carattere finale di \ x00, il che impedisce problemi con i nomi di file che contengono spazi.

il '-0' su xargs dice che si aspettano nomi di file che finiscono con \ x00 invece di resi.

e il tuo comando grep ...

Praticamente capito.


MODIFICARE::

Dal tuo aggiornamento:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

dovrebbe aiutare. (Aggiunto -L dalla risposta di @ rush, buon lavoro)

Ho l'idea che il tuo grep abbia bisogno dell'opzione '-i' o di essere meno esplicito.

Prova il comando in parti ... QUESTO nome di file di output sembra corretto?

find . -type f -iname "*pb.java"

In tal caso, è probabile che il tuo problema sia che il tuo modello di ricerca grep non corrisponda (errore di ortografia? Succede!), O semplicemente non ci sono corrispondenze.

Caso peggiore assoluto:

grep -riL "something" *

farà MOLTO più lavoro alla ricerca di tutto, ma dovrebbe darti un po 'di output.


Ho provato le tue modifiche e non sto ancora ottenendo il risultato che mi aspetto. Proverò ad aggiornare la domanda per renderla più chiara.
Hyangelo,

Se l'autore della domanda vuole solo trovare i nomi dei file, il grep non dovrebbe essere 'grep -l -v'?
Bruce Ediger,

sta cercando contenuti specifici nei file * .java
lornix il

xargs -0 grep -v "something something"dovrebbe essere xargs -0 grep -v "something something" /dev/nullaltrimenti otterrai risultati strani quando find non produce file corrispondenti.
James Youngman,

{Grin} sì, da qualche parte la logica è diventata tutta pelosa. Niente come un test multiplo a logica falsa inversa per farti male alla testa.
Lornix,

4

Il computer è un computer: sta facendo quello che gli hai detto di fare invece di quello che volevi che facesse.

grep -v "something something"stampa tutte le righe che non contengono something something. Ad esempio, stampa due righe tra le tre seguenti:

hello world
this is something something
something else

Per stampare file che non contengono da extends SomethingSomethingnessuna parte, utilizzare l' -Lopzione:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

Alcune versioni di grep non hanno l' -Lopzione (non è specificato da POSIX ). In caso contrario, non stampare nulla e utilizzare il codice di ritorno per fare in modo che la shell chiamante faccia tutto ciò che dovrebbe fare.

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

In alternativa, usa awk.

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

Su Linux o Cygwin (o altri sistemi con GNU grep), non è necessario utilizzare find, poiché grepè in grado di ripresentarsi.

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

Se la tua shell è ksh o bash o zsh, puoi fare in modo che la shell esegua la corrispondenza del nome file. Su bash, esegui set -o globstarprima (puoi metterlo nel tuo ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

Wow, questo è ancora meglio. Stavo usando 'extends (/ s) + SomethingSomething' che sembrava funzionare per quanto potevo dire. C'è qualche differenza con questa sintassi con quella specificata nella versione estesa di RegEx?
Hyangelo,

@Hyangelo \sè un'estensione grep GNU, che penso sia sinonimo di [[:space:]].
Gilles 'SO- smetti di essere cattivo' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.