2

I'm trying to pipe the output of a grep search into the input of another grep. Such as:

grep search_query * | grep -v but_not_this

But the second grep is not using the output of the previous search. It looks like the second grep is just using * instead. For example,

grep lcov *                                                                                          
tst/bits/Module.mk:21:$(call func_report_lcov)
tst/drivers/Module.mk:27:$(call func_report_lcov)

But when I want to filter out the results containing "call",

grep lcov * | grep -v call
...

Grep gives me every single line in my workspace that doesn't contain "call".

Environment Info:

  • This is happening in both bash and fish
  • I have aliased the grep command like so alias grep='grep -nR --color=always'

Anything else I might be missing?

  • 2
    grep does not descend into subdirectories without the -r/-R option. Do you have a function or script named grep? What does type -a grep show (in bash)? – glenn jackman Feb 14 at 22:02
5

The alias is what is causing it. From man grep, the -R option causes grep to "read all files under each directory, recursively". Hence, the part after the pipe ignores the output from the first grep, and instead greps through all files recursively from the current directory.

You can bypass the alias and use vanilla grep with \grep. Hence the following should give you what you expect.

grep lcov * | \grep -v call

However, I personally think that putting -R in the alias is confusing.

  • 1
    The main issue here is that GNU grep, when using -R and when not given a filename operand, will act recursively on the contents of the current directory. Other grep implementations don't use . as the default file operand when -R is used and no file operand is given (OpenBSD grep, for example, complains with grep: warning: recursive search of stdin). – Kusalananda Feb 14 at 22:25
  • In a script you could use /bin/grep or $(which grep) instead to make sure there is no alias set. – Freddy Feb 15 at 0:05
  • @Freddy Generally scripts wouldn't source .bashrc. – Sparhawk Feb 15 at 0:09
  • @Sparhawk Oh yes, how true. – Freddy Feb 15 at 0:16
0

Interesting. This appears to be correct, looks like the devil's in the details.
grep "search_query" *
could be different than
grep search_query *
which could be different again from grep 'search_query' * Try this:
grep search_query * > /tmp/foo grep -v but_not_this /tmp/foo Does the file /tmp/foo contain what you want?
Does "grep -v but_not_this" give the answer you want?
replace grep with \grep to unalias it it and see if that works.

  • Why "could be different"? All the three commands are the same, right? What difference does single/double-quoting make here? – Sparhawk Feb 14 at 22:27
  • It has to do with substitutions. If you are using $ or special characters. Double quotes mean "Substitute Now." Single quotes mean 'Let the program do the substitution.' Suppose I set my_var to Scottie. grep "$my_var" foo becomes grep Scottie foo But grep '$my_var' foo looks for the word $my_var in the file foo – Scottie H Feb 14 at 22:36
  • Yes, but in the question it's just a string lcov. – Sparhawk Feb 15 at 0:09
  • Have you triedto unalias both greps? useing the backslash on BOTH greps? Or unaliasing the grep completely <br> If you send the first gerp to a file, does that file contain what you expect?<br> If rou run the second grep on the file, do you get the correct result? – Scottie H Feb 15 at 1:17
  • Because you have -R in the grep, you are searching EVER non-hidden file in your current directory and EVERY non-hidden SUBdirectory. To see what I mean, run this command: ls -R * Are ALL of those the files you want to grep? – Scottie H Feb 15 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.