Why doesn't redirecting a loop work as intended? (Bourne shell

Why doesn't redirecting a loop work as intended? (Bourne shell

Take the following example:

foo=bar

while read line
do
# do something with $line
foo=bletch
done < /etc/passwd

echo "foo is now: $foo"

Despite the assignment ``foo=bletch'' this will print
``foo is now: bar'' in many implementations of the Bourne shell.
Why? Because of the following, often undocumented, feature of
historic Bourne shells: redirecting a control structure (such as
a loop, or an ``if'' statement) causes a subshell to be created,
in which the structure is executed; variables set in that
subshell (like the ``foo=bletch'' assignment) don't affect the
current shell, of course.

The POSIX 1003.2 Shell and Tools Interface standardization
committee forbids the behaviour described above, i.e. in P1003.2
conformant Bourne shells the example will print ``foo is now:
bletch''.

In historic (and P1003.2 conformant) implementations you can use
the following `trick' to get around the redirection problem:

foo=bar

# make file descriptor 9 a duplicate of file descriptor 0 (stdin);
# then connect stdin to /etc/passwd; the original stdin is now
# `remembered' in file descriptor 9; see dup(2) and sh(1)
exec 9<&0 < /etc/passwd

while read line
do
# do something with $line
foo=bletch
done

# make stdin a duplicate of file descriptor 9, i.e. reconnect
# it to the original stdin; then close file descriptor 9
exec 0<&9 9<&-

echo "foo is now: $foo"

This should always print ``foo is now: bletch''.
Right, take the next example:

foo=bar

echo bletch | read foo

echo "foo is now: $foo"

This will print ``foo is now: bar'' in many implementations,
``foo is now: bletch'' in some others. Why? Generally each part
of a pipeline is run in a different subshell; in some
implementations though, the last command in the pipeline is made
an exception: if it is a builtin command like ``read'', the
current shell will execute it, else another subshell is created.

POSIX 1003.2 allows both behaviours so portable scripts cannot
depend on any of them.



Home FAQ