Reputation: 374
I'm facing to a problem that I'm not able to explain. I've to recode a shell, and there is a weird behavior for me.
echo test >&2 2>&1
This kind of command is writing on stderr (so with the first redirection), why the second redirection isn't impacting the output destination ? Why the output isn't on stdout ?
I saw some stuff that redirection is happening before executing command, from left to right, so why the second redirection is not cancelling the first one ?
Thanks in advance.
edit: I'm running my script on bash.
Upvotes: 0
Views: 53
Reputation: 246807
x>&y
means "redirect file descriptor x to whatever fd y is currently pointing to.
Redirections are processed strictly left to right.
So, >&2 2>&1
points fd 1 to something like /dev/stderr, and then points fd 2 to /dev/stderr also.
If you want to swap stderr and stdout, you need a 3rd file descriptor:
(echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-
# ................................................ A .. B .. C .. D
# A. fd 3 = /dev/stdout
# B. fd 1 = /dev/stderr
# C. fd 2 = /dev/stdout
# D. fd 3 is closed
Let's put that in a function for easier testing
fdtest() { (echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-; }
Run it
$ fdtest
test to stdout
test to stderr
Throw away standard error (we expect to see the "stderr" message on standard out).
$ fdtest 2>/dev/null
test to stderr
Throw away standard out (we expect to see the "stdout" message on standard err).
$ fdtest 1>/dev/null
test to stdout
Upvotes: 2
Reputation: 212248
cmd >&2 2>&1
is very different than cmd 2>&1 >&2
, since the redirections occur in a different order. Suppose the command is invoked from a process which has fd 1 attached to a file named 'output' and fd 2 attached to a filed named 'error'. Then cmd >&2 2>&1
will redirect the stdout of cmd
to the file named error
and then redirect stderr of cmd
to whatever fd 1 is connected to, namely the file named error
. But cmd 2>&1 >&2
will first redirect fd 2 to 'output' and the redirect fd 1 to the same place. In other words, cmd >&2 2>&1
writes everything to stderr, and cmd 2>&1 >&2
writes everything on stdout.
Upvotes: 1