rSim
rSim

Reputation: 374

Shell, behavior of conflicting redirection

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

Answers (2)

glenn jackman
glenn jackman

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

William Pursell
William Pursell

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

Related Questions