How to redirect STDERR to STDOUT but ignore the original STDOUT?

I have a program whose output STDERR I want to test and run grep , etc.

So I could redirect it to STDOUT and use grep, but the problem is that I don't want the original STDOUT content.

So this one will not do

 cmd 2>&1 | grep pattern 

because he will mix the original STDOUT and STDERR.

And this one does not work, as grep does not read the output of STDERR:

 cmd 1>/dev/null | grep pattern 

But this one will not work either:

 cmd 1>/dev/null 2>&1 | grep pattern 

because the output will be completely empty, since everything will be written to /dev/null .

But should there be an easy way to do this?

+50
redirect bash stdout
Feb 14 '09 at 20:27
source share
3 answers

What does not work:

Reason for the last command you quoted:

 cmd 1>/dev/null 2>&1 | grep pattern 

not working, stems from confusion in the order in which the redirection works. You expected the last cited redirection to be applied to those that were in front of it at each output, so that the output of the original descriptor of the original output file (1) will go to / dev / null, and the output to the standard error file descriptor (2) will be Go to the original output standard.

However, this is not how shell redirection works. Each redirection causes the file descriptors to be "redirected", closing the "source" and duplicating the "destination" in it (see the man dup(2) and close(2) pages) in order. This means that in your command, standard output is first replaced by /dev/null , and then standard error is replaced by standard output, which is already /dev/null .

What works:

Therefore, to get the desired effect, you just need to cancel the redirects. You will then have a standard error going to standard output, and the original standard output is /dev/null :

 cmd 2>&1 >/dev/null | grep pattern 

(note that 1 to > not required - the default value is used for standard output redirection output)




Appendix: Charlie mentioned redirecting to &- to close the file descriptor. If you use an interactive shell that supports this extension ( bash and some other implementations, but not all, and this is not the standard ), you can also do it like this:

 cmd 2>&1 >&- | grep pattern 

It may be better - it can save some time, because when a command tries to write to standard output, the write call may fail immediately, without waiting for the context to go to the kernel and the /dev/null driver to process (depending on the system implementation calling - some may catch this in the libc function, and some may also have special handling for /dev/null ). If there is a lot of output that can be useful, and it is faster to enter.

This will work mainly because most programs do not care about what they cannot write to standard output (who really checks the return value of printf ?) And will not mind closing the standard output. But some programs can generate a fault code if write does not work - processors usually block, programs use some careful library for I / O or log stdandard output. Therefore, if it does not work, remember that this is the probable cause and try /dev/null .

+85
Feb 14 '09 at 20:45
source share

First close STDOUT:

 1>&-, >&- 

See here .

+2
Feb 14 '09 at 20:31
source share

I would try something simple:

 cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file 
-four
Feb 14 '09 at 20:33
source share



All Articles