Question

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.

Was it helpful?

Solution

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>&-

OTHER TIPS

Huh, I've never seen that .... anyway ...it seems that is essentially saying firstly ... send 3 to the address of 2 .... then send two to the address of 1 .... then send one to the address of 3...which from the first step, we know is the original address of two ... so you've swapped them .... haven't tested that out myself though....

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top