In Cygwin, I wrote a bashrc function rg, which is basically a recursive grep statement:
rg () {
find . -type f -exec grep -il $1 {} \;
}
This works well, but now I need to run an additional grep on each output line to check for another word. I basically want it to list each file that contains both words (not necessarily on the same line). I tried this command:
rg Word1 -exec grep -il Word2 {} \;
This seems to just output the same files containing "Word1".
I tried this next command, and I thought it'd just output "Ha" on each line, but it still keeps listing the files from the "rg Word1" statement.
rg Word1 -exec echo "Ha" \;
So I'm clearly doing something wrong here. Can anyone clear my confusion? I'm aware there's a way to do this within grep itself, but that seems to work on a per-line basis. I'm guessing what I'm trying to do is pretty common. Also once I get this working, I'd like to put it in another bashrc function for convenience. Not sure if that's makes it more complicated or not.
If you have it or can get it, the xargs
command collects arguments for a command from its standard input, then runs the designated command. You could combine that with your rg
function to filter the function's output. For example,
rg Word1 | xargs grep -il Word2
The arguments xargs
reads from its standard input -- the file names emitted by function rg
-- will be appended to the given command (grep -il Word2
), and the resulting command run. If xargs
's input is long enough, the arguments will be split across multiple invocations of the grep command, which makes no difference to the output (in this case), but avoids command execution failing on account of too many arguments.
Consider also structuring function rg
in the same way (i.e. using xargs
) to minimize the number of separate grep
processes that are executed. Starting a new process is one of the more expensive things you can do.