TL;DR
You can't pipe the names, but you can supply the names (as pathspecs) to one of the two git grep
commands.
(Oddly, the --and
should have done what you wanted in the first place—I'm just answering the question of how to do it without --and
.)
Moderately long
It's not clear precisely what result you'd like, but on the assumption that what you want is:
there are two somewhat obvious ways to attempt to make that happen, but one of them doesn't work because Git won't match across newlines.1 So we're left with the other obvious method:
- First, use
git grep -l
to produce a list of files matching the first expression.
- Then, use
git grep -l
to produce a list of files matching the second expression, optionally, starting only with those files produced by the first git grep
.
To combine these as an and operation, you have the fairly obvious option of using one of the two git grep -l
outputs as a series of pathname arguments to the other git grep
. Note, however, that git grep
takes pathspec arguments, rather than path name arguments, after the --
that delimits them (see the documentation for details). This means that if any of your file names have pathspec metacharacters in them, this simple shell expansion may fail. It's also probably a good idea to verify that the first grep
actually lists some files, but combining them into one bash style command:
git grep -l pattern2 -- $(git grep -l pattern1)
may often suffice.
To combine the above two as an or operation (list files that contain either pattern), it's easiest to just use one git grep
with more than one pattern. Note, however, that you can run multiple git grep -l
operations with the resulting file names directed to a temporary file, then use a program like comm
to report what's common and unique to each set of results. (This assumes you have comm
in your command-line-interpreter toolbox.) Using comm
also gets around the pathspec issues with peculiar file names like (top)file.c
or got*you.sh
or whatever.
1If Git did match across newlines, you could use the extended or Perl pattern: (foo(.|\n)*bar)|(bar(.|\n)*foo)
to allow arbitrary text between the two other patterns foo
and bar
, with either pattern in either order.