12

When trying to filter very long output from make for specific warnings or error messages, the first idea would be something like this:

$ make | grep -i 'warning: someone set up us the bomb'

The result is not fully satisfying, though. The output will not just contain the filter results from grep but also stdout and stderr messages from other tools that are used in the make target somewhere.

The question now is:

  1. Where does the other output come from?
  2. How to write the filter command that the output will only contain the filtered lines?
erikbstack
  • 12,878
  • 21
  • 81
  • 115

3 Answers3

13

To answer the questions:

  1. The pipe only connects the stdout of make to the stdin of grep. make's stderr is still connected to the terminal in will therefore be printed without filtering.
  2. The solution is connect make's stderr to its stdin and ignore the stdin

    $ make 2>&1 >/dev/null | grep -i 'warning: someone set up us the bomb'
    

This only prints the output of grep, but nothing from make or other tools like rm.

erikbstack
  • 12,878
  • 21
  • 81
  • 115
  • Thanks to [fedorqui](http://stackoverflow.com/users/1983854/fedorqui) I got the idea to [search something else](https://www.google.de/search?q=redirect+stderr+to+pipe), which actually helped me finding [a correct answer](http://stackoverflow.com/a/2342841/131120). – erikbstack Sep 20 '13 at 10:32
2

I just wanted to see the warnings from my compiler. Using the silent option of make got me close to where I wanted.

From the make man page:

-s, --silent, --quiet                                                                                                                       
Silent operation; do not print the commands as they are executed.

There were still a large number of compiler warnings I wanted to ignore so I set the CFLAGS when I called make

for example:

make -s CFLAGS="-Wno-deprecated-declarations"

If you are using libtool this also is very hand

make LIBTOOLFLAGS='--silent' --quiet

If I'm only interested in a specific file or set of files I use the touch command followed by a silent make.

touch foo.c; make -s CFLAGS="-Wno-deprecated-declarations"

Originally I set out trying to grep make output, but it's cleaner to call make silently, control your compilation warnings, and touch files to limit the compilation. After all this you could still use grep, but I would look at the build system and compiler manpages first.

f3xy
  • 737
  • 11
  • 15
  • Could you rephrase a little? It's hard for me to see the relevance between your answer and the question. – erikbstack May 04 '16 at 10:32
  • In my case I was trying to see compilation warnings which are printed when make is executed. It would be useful to know who printed the warnings you were interested in and what the actual warning message was. Without this information the original question is simply asking how to redirect output in a shell which is covered in [BASH Programming - Introduction HOW-TO](http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html) and also most likely a duplicate question. – f3xy May 04 '16 at 20:09
1

Exclude the stderr:

make 2>/dev/null | grep -i 'warning: someone set up us the bomb'

Example

$ ls
hello
$ ls hello bye
ls: cannot access bye: No such file or directory # <--- this is stderr
hello
$ ls hello bye 2>/dev/null # <--- stderr are sent to /dev/null, so don't appear
hello

As seen in the comments, all make output is given as stderr, so that the first solution would not match anything at all. Hence my proposal is to use the following:

make 2> >(tee make_output.log >&2)

And then grep the make_output.log. As seen on How do I write stderr to a file while using “tee” with a pipe?.

Example

$ ls aaa
ls: cannot access aaa: No such file or directory
$ ls aaa 2> >(tee stderr.log >&2)
ls: cannot access aaa: No such file or directory
$ cat stderr.log 
ls: cannot access aaa: No such file or directory
Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • What if you do `make | tee myfile` and then grep myfile? – fedorqui Sep 18 '13 at 13:51
  • Yes. What I see is that `make` output is taken as `stderr`. As `grep` takes the stdin, your `grep` is not doing anything. I think the `tee` solution could work if you make it a temporal file and then delete. `make | tee myfile; grep text myfile; rm myfile` for example – fedorqui Sep 18 '13 at 13:55
  • You'd better check `make` man page to see if any option provide better output. As I said before, the current `make` returns you stderr which has to be handled differently. – fedorqui Sep 18 '13 at 14:23
  • @erikb85 in case it was your downvote, take into consideration that downvoting people that try to help you is not the best way to make them feel like doing it again. In case it is someone else, it would be good to know the reasons, since my answer is not wrong. – fedorqui Sep 19 '13 at 12:28
  • I tried to explain to you before that it is actually wrong, because it doesn't lead to the desired result. The expected result is only get output from grep. The actual result is that there is no output at all. – erikbstack Sep 20 '13 at 09:52
  • I tried to explain that the output is given with stderr, hence the proposal of tee. You refused it with your own reasons, that I respect, and I suggest to check `man make`. I just updated my answer so all my explanations are in the answer. And I finish here, don't want to lose more of time on something that is then downvoted. – fedorqui Sep 20 '13 at 10:01