L'uso di xargs nelle risposte sopra non è necessario; puoi ottenere la stessa cosa in questo modo:
find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
grep -q significa eseguire in silenzio ma restituire un codice di uscita che indica se è stata trovata una corrispondenza; find può quindi utilizzare quel codice di uscita per determinare se continuare a eseguire il resto delle sue opzioni. Se -exec grep -q <string-to-match> {} \; restituisce 0, quindi eseguirà -not -exec grep -q <string-not-to-match>{} \; . Se anche questo restituisce 0, eseguirà -print , che stampa il nome del file.
Come ha notato un'altra risposta, usando find in questo modo ha grandi vantaggi rispetto a grep -Rl dove vuoi solo cercare file di un certo tipo. Se, d'altra parte, vuoi davvero cercare tutti i file, grep -Rl è probabilmente più veloce, in quanto utilizza un grep processo per eseguire il primo filtro per tutti i file, invece di un grep separato processo per ogni file.
Prova questo:
grep -rl <string-to-match> | xargs grep -L <string-not-to-match>
Spiegazione:grep -lr fa in modo che grep restituisca in modo ricorsivo (r) un elenco (l) di tutti i file che contengono <string-to-match> . xargs esegue un ciclo su questi file, chiamando grep -L su ciascuno di essi. grep -L produrrà solo il nome del file quando il file non contiene <string-not-to-match> .
Queste risposte sembrano corrispondere a ENTRAMBE stringhe. Il seguente comando dovrebbe funzionare meglio:
grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'