I'd like to find all xml files containing 'foo', but not containing 'bar'. The command I've put together looks like this:

find -iname "*.xml" -print0 |
  xargs -0 grep -FlisZ "foo" |
  xargs -0 grep -Flisv "bar"

However the final grep command doesn't seem to exclude files that contain 'bar'. Have I chained the commands correctly?

p.s. I know this can be written in many different ways (and probably a single grep command). However I'm interested in why my chaining is broken.

p.p.s The filenames contains spaces (hence the -print0 in find, the -0 in xargs and the -Z in grep)

  • Thanks Don, but is there a reason why my chained command don't work?
    – Fidel
    Nov 2, 2015 at 11:22
  • 4
    Your last grep doesn't exclude files that contain bar because you are using -v bar that is list files that contain at least one line not matching bar. Create a file with just one line containing foobar and you'll see it won't be listed; as soon as you add another line to that file, it will be listed. In this case you will have to use the last grep like this grep -FLis (note the L instead of l) Nov 2, 2015 at 11:28
  • @don_crissti: You should make that into an answer.
    – Dubu
    Nov 2, 2015 at 13:05
  • Thank you Don, that works well. The full command is now: find -iname "*.xml" -print0 | xargs -0 grep -FlisZ "foo" | xargs -0 grep -FLis "bar"
    – Fidel
    Nov 2, 2015 at 15:04
  • @don_crissti: If you think this question is a duplicate, you should mark it as such. (I think it is different enough.) If not, formulating your comment as an answer would clearly help others to find the solution.
    – Dubu
    Nov 2, 2015 at 15:34


Browse other questions tagged .