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)? Feb 14, 2019 at 22:02

2 Answers 2


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.

  • 5
    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, 2019 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, 2019 at 0:05
  • @Freddy Generally scripts wouldn't source .bashrc.
    – Sparhawk
    Feb 15, 2019 at 0:09
  • @Sparhawk Oh yes, how true.
    – Freddy
    Feb 15, 2019 at 0:16
  • It's not confusing, it's wacky
    – n.caillou
    May 27, 2019 at 1:43

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, 2019 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, 2019 at 22:36
  • Yes, but in the question it's just a string lcov.
    – Sparhawk
    Feb 15, 2019 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, 2019 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, 2019 at 1:42

You must log in to answer this question.

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