Find files containing one string but not the other
As long as your filenames do not contain spaces, tabs, newline or wildcard characters, and if your grep
supports the -L
option, you can do it as follows:
$ cat file1
stringA
stringC
$ cat file2
stringA
stringB
$ grep -L stringB $(grep -l stringA file?)
file1
The grep
executed in the subshell $()
, will print all filenames which contain stringA
. This filelist is input for the main grep
command, which lists all files that do not contain stringB
.
From man grep
-v, --invert-match Invert the sense of matching, to select non-matching lines. (-v is specified by POSIX.) -L, --files-without-match Suppress normal output; instead print the name of each input file from which no output would normally have been printed. The scanning will stop on the first match. -l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match. (-l is specified by POSIX.)
With GNU tools:
grep -lZ stringA ./*.txt |
xargs -r0 grep -L stringB
-L
, -Z
, -r
, -0
are GNU extensions sometimes but not always found in some other implementations.