0

I know basic redirection, but I'm confused how should I handle situations with multiple file descriptors at once.

For example, I have script that writes to FDs 1, 2 and 3. I want to output script::1 and script::2 to stderr and script::3 to stdout.

Something like this, which doesn't work:

./script.sh \
    1>&2 \
    2>&2 \
    3>&1

How does redirection how I would like to do work? I have no idea what to search for.

I know I can work around this, and I actually already have to workaround ready, but I'd like to know how to do advanced magic like this. Maybe something with redirecting to /proc/self/fd/{1,2}?

 +-----------+            +-----------------+
 |           >1 ---+---- 2>                 |
 | script.sh >2 ---^      |       TTY       |
 |           >3 -------- 1>                 |
 +-----------+            +-----------------+
0

1 Answer 1

3

I have script that writes to FDs 1, 2 and 3. I want to output script::1 and script::2 to stderr and script::3 to stdout.

Just change the order:

./script.sh 3>&1 1>&2

[ you can omit the 2>&2, you only have to that in ksh for fds greater than 2 ;-) ]

Most confusion with fd redirecting operators comes from the fact that people seem to attach magical properties to the > or < characters -- in fact, >& and <& are 100% identical.

Every time you see p>&q or p<&q where p and q are numbers, parse it as a fd_p = fd_q assignment.

Then it's easy to see that if you start with fd1: out and fd2: err, fd3=fd1 fd1=fd2 evaluated from left to right will result in fd1: err, fd2: err and fd3: out.

5
  • Thanks! One more question, so in my example, I pointed fd1 to whatever fd2 pointed to (stderr) and the last redirection pointed fd3 to whatever fd1 pointed to, which was set to stderr by that time. But in your example, you first pointed fd3 to whatever fd1 pointed to (stdout) and then pointed fd1 to whatever fd2 pointed to (stderr), correct?
    – SoptikHa
    Commented Feb 5, 2020 at 17:12
  • 1
    Yes, that's correct.
    – user313992
    Commented Feb 5, 2020 at 17:38
  • Huh. I mean you gotta admit that having two different syntaxes which are suggestive of meaning opposite things, but which actually mean the same thing, is kind of confusing! Thank you for pointing that out.
    – glaebhoerl
    Commented Dec 10, 2020 at 8:11
  • It's incorrect to say, >& and <& are identical. Besides redirecting file descriptors, one of them is still able to redirect output into files (when not a number or hyphen is given on the right side). echo hello >& log will write a file log whereas echo hello <& log will actually be a redirect error. I would rather choose the symbol to convey intent. If the command wants to read from a file descriptor, <&, if it should be written, >&. I don't know, if it enforces read or write direction. The version <>& does not exist. For only file descriptor redirection, you could be right. Commented Jun 10 at 2:51
  • Otherwise, the main difference between <& and >& only seems to be the default file descriptor value they redirect to. exec {x}>log; echo hello world <&$x- will not write the log file but will send output to /dev/stdout. However exec {x}>log; hello world >&$x- and exec {x}>log; hello world 1<&$x- will. Commented Jun 10 at 3:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .