As I understand the bash documentation both | and < redirect stdin. So, cmd | foo
and foo < <(cmd)
should be more or less equivalent. However, for the bash-internal read command this doesn't seem to be the case. E.g., if I enter
a=""; b=""; read a b < <(echo a b); echo $a $b
it prints out a b
, while
a=""; b=""; echo a b | read a b; echo $a $b
prints out nothing. On the other hand, if I enter
a=""; b=""; cat < <(echo a b) >foo1
a=""; b=""; echo a b | cat > foo2
the files foo1 and foo2 are exactly the same. So my question is: what is the difference with both forms when the read command is involved (or in general)? They should see exactly the same redirected input. While the < <(...)
form works, I find it pretty unreadable and would much prefer to use the pipe form.
Best Answer
The act of pipelining executes
read
in a subshell, whereas process substitution does not. For most use cases, this isn't a problem, but in this instance you want to directly affect the shell (by manipulating variables). Becauseread
has been invoked in a subshell, only the subshell is affected. As such, any actions that you might wish to perform on them will need to also be performed in the subshell; for example: