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
done < <(cat test.txt)
echo "$REPLY" # Prints foo

unset REPLY
cat test.txt | while read
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.

  • Only in ATT ksh (ksh88 and ksh93, but not pdksh) and in zsh does the right-hand side of a pipe run in the parent shell. – Gilles Oct 26 '11 at 7:28

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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.