Friday, January 10, 2014

How to pipe STDERR only

Occasionally I may need to pipe STDERR somewhere, e.g. to less, grep, or head. It may not be immediately obvious how to accomplish this.

If I simply do:
$ my_program | less
STDOUT will be sent to less, and STDERR will continue to go to the console.

If I do this:
$ my_program >/dev/null | less
Nothing will be sent to less, and STDERR will still go to the console.

While it may look like I'm not making any progress here, I am actually just one small step from my goal. As Jonathan Leffler writes in his answer to this question on, the solution is to first redirect STDERR to &1, which is the device/file descriptor to which STDOUT is set to write to, and _then_ redirect STDOUT to /dev/null:
$ my_program 2>&1 >/dev/null | less
This sends STDERR to less, and STDOUT to /dev/null -- which is what I wanted.

In the comments, Jonathan explains exactly how this works:
One must read the redirection chains from left to right since that is the way the shell processes them. The first operation is the 2>&1, which means 'connect stderr to the file descriptor that stdout is currently going to'. The second operation is 'change stdout so it goes to /dev/null', leaving stderr going to the original stdout, the pipe. The shell splits things at the pipe symbol first, so, the pipe redirection occurs before the 2>&1 or >/dev/null redirections, but that's all; the other operations are left-to-right. (Right-to-left wouldn't work.)

No comments:

Post a Comment