I am trying to accomplish the following result with bash:

  1. grep files for some substring.
  2. take the filenames (which can contain spaces) for these files and print them.
  3. after printing each filename I want to grep again, however this time inside that file only.

So the result looks like this:

it works!
it works!

I tried constructing a command like this:

grep -irl "something" . | xargs -I % sh -c 'echo "%"; cat "%" | grep -i "another thing" "%"'

Explanation: grep -l returns the filenames. Then I print those filenames with echo "%" and then I want to grep inside the file.

But no luck. What is the lesson here?

To clarify: My actual problem/goal is to find all files that contain a string A but do not contain a string B as well.

More clarification: I want something like grep A | grep -v B but I want a list of all files that matched A, as well.

  • This (didn't test) ? 2nd xargs -> grep -irl "something" . | xargs -I % sh -c 'echo "%"; cat "%" | xargs -I % grep -i "another thing" "%"
    – Jacques
    Commented Dec 18, 2019 at 13:10
  • You're sending all grep output to xargs.
    – Kusalananda
    Commented Dec 18, 2019 at 13:13
  • No I want to first grep to find some files and then grep inside those files. Your command seems to grep over all files twice.
    – scrrr
    Commented Dec 18, 2019 at 13:13
  • Do you need to see the output of the first grep?
    – Kusalananda
    Commented Dec 18, 2019 at 13:14
  • Kusalananda: the first grep returns the filenames (option -l) only
    – scrrr
    Commented Dec 18, 2019 at 13:14

1 Answer 1


What is the lesson here?

Probably do not over-egg the pudding.

% (
>   grep -l -r -- "$patternA" . |
>   tee /dev/fd/7 |
>   xargs grep -L -- "$patternB"
> ) 7>&1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .