It's much easier to visualize things if you think about what's really going on with "redirects" and "pipes." Redirects and pipes in bash do one thing: modify where the process file descriptors 0, 1, and 2 point to (see /proc/[pid]/fd/*).
When a pipe or "|" operator is present on the command line, the first thing to happen is that bash creates a fifo and points the left side command's FD 1 to this fifo, and points the right side command's FD 0 to the same fifo.
Next, the redirect operators for each side are evaluated from left to right, and the current settings are used whenever duplication of the descriptor occurs. This is important because since the pipe was set up first, the FD1 (left side) and FD0 (right side) are already changed from what they might normally have been, and any duplication of these will reflect that fact.
Therefore, when you type something like the following:
command 2>&1 >/dev/null | grep 'something'
Here is what happens, in order:
- a pipe (fifo) is created. "command FD1" is pointed to this pipe. "grep FD0" also is pointed to this pipe
- "command FD2" is pointed to where "command FD1" currently points (the pipe)
- "command FD1" is pointed to /dev/null
So, all output that "command" writes to its FD 2 (stderr) makes its way to the pipe and is read by "grep" on the other side. All output that "command" writes to its FD 1 (stdout) makes its way to /dev/null.
If instead, you run the following:
command >/dev/null 2>&1 | grep 'something'
Here's what happens:
- a pipe is created and "command FD 1" and "grep FD 0" are pointed to it
- "command FD 1" is pointed to /dev/null
- "command FD 2" is pointed to where FD 1 currently points (/dev/null)
So, all stdout and stderr from "command" go to /dev/null. Nothing goes to the pipe, and thus "grep" will close out without displaying anything on the screen.
Also note that redirects (file descriptors) can be read-only (<), write-only (>), or read-write (<>).
A final note. Whether a program writes something to FD1 or FD2, is entirely up to the programmer. Good programming practice dictates that error messages should go to FD 2 and normal output to FD 1, but you will often find sloppy programming that mixes the two or otherwise ignores the convention.
|&
to pipe both stderr and stdout (which isn't what the OP is asking exactly, but pretty close to what I guess your proposal could mean). – Leeanneleeboard2|
otherwise mean in bash? – Exurbaniteecho 2 | tee my_file
versusecho 2|tee my_file
. – Vocalist2 |
is not2|
indeed, I would not call it ambiguous, more like potentially error-inducing, just likeecho 2 > /myfile
andecho 2> /myfile
which is even more of an issue. Anyway it's not about saving a few keystrokes, I find the other solutions convoluted and quirky and have yet to wrap my head around them which is why I would just fire uprc
which has a straightforward syntax for determining the stream that you want to redirect. – Exurbanite