[ Usenet FAQs | Search | Web FAQs | Documents | RFC Index ]
Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Single Page
Top Document: Unix - Frequently Asked Questions (3/7) [Frequent posting]
Previous Document: How can a process detect if it's running in the background?
Next Document: How do I run ... interactive programs from a shell script ... ?
-
Search the FAQ Archives
Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Single Page
Top Document: Unix - Frequently Asked Questions (3/7) [Frequent posting]
Previous Document: How can a process detect if it's running in the background?
Next Document: How do I run ... interactive programs from a shell script ... ?
Why doesn't redirecting a loop work as intended? (Bourne shell)
3.8) 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.
Top Document: Unix - Frequently Asked Questions (3/7) [Frequent posting]
Previous Document: How can a process detect if it's running in the background?
Next Document: How do I run ... interactive programs from a shell script ... ?
Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Single Page
[ Usenet FAQs | Search | Web FAQs | Documents | RFC Index ]
Send corrections/additions to the FAQ Maintainer:
tmatimar@isgtec.com (Ted Timar)
Last Update July 24 2008 @ 00:16 AM