Order of redirection and process substitution

289 Views Asked by At

What is the process order of redirection and process substitution? One line command to process pre error works Ok.

{ echo hello;jiji jio; } 2> >(while read line;do echo "____$line";done) >right.log

While this order does not.

{ echo hello;jiji jio; } >right.log 2> >(while read line;do echo "____$line";done)
2

There are 2 best solutions below

0
On BEST ANSWER
$ { echo hello;jiji jio; } 2> >(while read line;do echo "____$line";done) >right.log
____jiji: command not found
$ cat right.log 
hello

In the above, it is like jiji jio 2>&1 | while read line;do echo "____$line";done and echo hello >right.log.

$ { echo hello;jiji jio; } >right.log 2> >(while read line;do echo "____$line";done)
$ cat right.log 
hello
____jiji: command not found

In the second, it is like { echo hello; jiji jio 2>&1 | while read line;do echo "____$line";done } >right.log. Remember that echo "____$line" portion triggers it to be redirected to >right.log (because it writes to stdout).

So yes, order does matter. In the second case >right.log redirection is remembered when processing 2> >(...) and whenever ... writes to stdout it is redirected to >right.log.

0
On

Redirections are processed left-to-right. That's certainly what Posix says: (Near the end of the prologue to section 2.7)

If more than one redirection operator is specified with a command, the order of evaluation is from beginning to end.

And the bash manual (v5.1) agrees:

Redirections are processed in the order they appear, from left to right. (Section 3.6)

So in the first case, when the >(...) subprocess is created, stdout has not yet been redirected, and so the original stdout is inherited by the subprocess, and that's where it sends its output (the line it read from the {...}'s stderr).

In the second case, stdout is redirected to right.log before the subprocess is created, so that's what the subprocess inherits as its stdout, and thus where it will echo its input. Thus, right.log ends up with both the line echoed by the main process and the error redirected into the subprocess and then echoed with leading underscores.

That seems to be the behaviour of bash 4.4 and bash 5.0, which are what I have handy.

Note, however, that redirection to a pipeline happens before any redirections in the command, even though the pipe operator is further to the right:

The standard input, standard output, or both of a command shall be considered to be assigned by the pipeline before any redirection specified by redirection operators that are part of the command. (Posix section 2.9.2).

That didn't seem relevant to this question, but it might be useful to know.