Bash Pipes – Pipes vs Process Substitution

bashpipeprocess-substitution

While trying the cat "$@" trick to read from either standard input or given files, it turned out that pipe and process substitution handle a missing trailing newline differently:

printf %s foo > test.txt

unset REPLY
while read
do
    :
done < <(cat test.txt)
echo "$REPLY" # Prints foo

unset REPLY
cat test.txt | while read
do
    :
done
echo "$REPLY" # Prints nothing!

Is this by design? Is this "feature" documented anywhere?

D'oh! @fered had the right idea – It's just another example of how variable values are lost because piped commands are run in a subshell.

Best Answer

Variables in a pipe never make it out of the pipe alive :)
Process substitution redirects the data to a file descriptor. Behind the scenes, that process is not the same as a | pipe. The following works, because it is all within the same pipe.

unset REPLY
cat test.txt | { 
  while read ;do : ;done
  echo "$REPLY" 
} # Prints foo!
Related Question