Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
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
up vote 11 down vote accepted

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!
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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