In numerouse places, I've found people suggesting that you can swap stderr with stdout as follows:
command 3>&2 2>&1 1>&3
This looks backwards to me. If we send 3 to 2 and then immediately send 2 to 1 (which now would appear to be sending both 3 and 2 to 1). I think there's something basic I don't understand about IO redirection, but I can't find anything which clarifies it.
You will find a detailed explanation at http://www.catonmat.net/blog/bash-one-liners-explained-part-three/ , section 21:
$ command 3>&1 1>&2 2>&3 Here we first duplicate file descriptor 3 to be a copy of stdout. Then we duplicate stdout to be a copy of stderr, and finally we duplicate stderr to be a copy of file descriptor 3, which is stdout. As a result we've swapped stdout and stderr.
There is more detail, and pictures, at the link given. The key insight is:
3>&1
means "3 points to where 1 is pointing". Then 1>&2
says "now 1 points to where 2 is pointing" (1 now points to stream 2, but 3 doesn't follow...), and finally 2>&3
says "now 2 points to where 3 is pointing (which is stream 1).
Graphically (but see link - it's much better than my ascii-art):
0 --> /dev/tty0
1 --> /dev/tty1
2 --> /dev/tty2
After 3>&1
:
0 --> /dev/tty0
1 --> /dev/tty1
2 --> /dev/tty2
3 --> /dev/tty1
After 1>&2
:
0 --> /dev/tty0
1 --> /dev/tty2
2 --> /dev/tty2
3 --> /dev/tty1
After 2>&3
:
0 --> /dev/tty0
1 --> /dev/tty2
2 --> /dev/tty1
3 --> /dev/tty1
As you can see, 1
and 2
have been swapped. The same link recommends closing temporary stream 3
with 3>&-