4 ms·
Since this is hackernews, can someone explain the rational behind putting the 2>&1 after the > ? I know it works, but this reads to me: command > file.txt 2>&1
by jcampbell1 14y ago
Since this is hackernews, can someone explain the rational behind putting the 2>&1 after the > ?
I know it works, but this reads to me:
command > file.txt 2>&1
"write the output of command to file.txt and then map the error output to stdout"
It makes so much more sense to write:
command 2>&1 > file.txt
There is clearly something in my brain that is confused about how redirection works.
- bodyfour 14y agoThink of it as saying "take fd 2 (stderr) and send it to the same place fd 1 is going now" So: $ command >file.txt 2>&1 first redirects fd=1 to file.txt and then has fd=2 go the same place. Where: $ command 2>&1 >file.txt first has fd=2 go the original place stdout was and then redirect fd=1 only to file.txt. Usually not what you want. If you really wanted file.txt to get only the stdout while simultaneously sending what used to be stderr to stdout I think you'd have to use another file descriptor like: $ command 3>&1 >file.txt 2>&3 That is, save the original stdout as fd=3, redirect stdout, then make stderr go the same place fd=3 is going.
- jrockway 14y ago&1 refers to file descriptor 1. a>&b calls dup2(2) with oldfd=b and newfd=a. So ordering matters. STDOUT starts out attached to fd=1, but if you dup something else to fd=1, the association "fd 1 is STDOUT" is forgotten. And that's exactly what usually happens; we replace fd 1 with one open to /dev/null, and then when we say 2>&1, that means to replace fd 2 (stderr) with whatever's at fd 1 (now /dev/null). When you write "command 2>&1 >/dev/null" that means something else, it means "send fd 2's output to what's currently at fd 1 (stdout)", and then "send what's currently at fd 1 to /dev/null". In other words, the source of a redirection is "by reference", but the destination of a redirection is "by value". If that makes any sense...
- tedunangst 14y agoYour second example puts stderr into the old stdout, then makes a new stdout go into the file. You have to redirect the files in the proper sequence to get the desired behavior. It is quirky if you don't expect it.
- shabble 14y agoI think this[1] is probably what you're looking for. If I'm understainding you correctly, the 2nd example will have mapped 2/stderr to &1 (stdout), before pointing stdout to the file, so you end up with both in the file. [1] http://wiki.bash-hackers.org/syntax/redirection#multiple_redirections http://wiki.bash-hackers.org/syntax/redirection#multiple_red...
- akkartik 14y agoSiblings have already responded to this well, so I'll just add an example: $ ls x ls: cannot access x: No such file or directory $ ls x >/dev/null 2>&1 $ ls x 2>&1 >/dev/null ls: cannot access x: No such file or directory The first command shows us trying to list a non-existent file, raising an error. The second sends stderr to stdout before sending stdout to null, suppressing all output. The third sends the error to stdout; any output on stdout would have been suppressed (can you come up with a way to verify this?)
- jrockway 14y agocan you come up with a way to verify this? perl -E 'say q{STDOUT!}; say {*STDERR} q{STDERR!}' (q{...} quoting to avoid ugliness of quotes inside quotes.)