The use of xargs in the answers above is not necessary; you can achieve the same thing like this:
find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
grep -q
means run quietly but return an exit code indicating whether a match was found; find
can then use that exit code to determine whether to keep executing the rest of its options. If -exec grep -q <string-to-match> {} \;
returns 0, then it will go on to execute -not -exec grep -q <string-not-to-match>{} \;
. If that also returns 0, it will go on to execute -print
, which prints the name of the file.
As another answer has noted, using find
in this way has major advantages over grep -Rl
where you only want to search files of a certain type. If, on the other hand, you really want to search all files, grep -Rl
is probably quicker, as it uses one grep
process to perform the first filter for all files, instead of a separate grep
process for each file.