The encapsulation of subshell processes makes it difficult for them to communicate through ShellVariables with the rest of the system. Consider the following fragment of Shell code:
while read line do lastline=$line; done < $TMPFILE echo "Last line is $lastline" read stdinline echo "Next Line of stdin is $stdinline"In this case, the variable $lastline is lost through the creation of a subshell to perform the I/O redirection for the while loop. Yet, at the same time, the conditions associated with Use Exec To Avoid Sub Shell are not met, since the read stdinline references standard input after the I/O redirection had taken place.
Therefore:
Save file descriptors to avoid a subshell. The following code saves the stdin file descriptor in file descriptor 3, and restores it after the exec.
exec 3<&0 <$TMPFILE while read line do lastline=$line; done echo "Last line is $lastline" exec 0<&3 3<&- read stdinline echo "Next Line of stdin is $stdinline"Notes:
This is a variant of UseExecToAvoidSubshell that works for the case that the stdin/stdout/stderr that is being redirected will be needed again. This is the technique the Korn shell uses to avoid the problems associated with creating subshells to perform I/O redirection.
there are subtle differences between different unix shells: the above example does not fail to set the lastline variable in bash, because bash executes the last command in a pipeline within the process of the shell itself. the variable would be lost if the while-loop is redirected to another command, though.