There are various threads going around that draw attention to how Bash spawns a sub-shell to handle while-loops, etc, which is why the value outside a while-loop is "not preserved".
Strangely enough I found this some time ago in the early stages of the AudioScope.sh development:-
Last login: Wed Aug 6 22:34:25 on ttys000
AMIGA:barrywalker~> for n in {1..10}; do printf "$n\n"; n=$((n+2)); done
1
2
3
4
5
6
7
8
9
10
AMIGA:barrywalker~> _
I still don't understand what is happening, as I would have thought that the "n" inside the loop would either create an error or be the equivalent of a "step of 2".
Would this be a bug or am I missing something...
@wisecracker remember that a for loop is just fetching the variable as a string from the parameter list one at a time it isn't incrementing the variable at all.
So you can see that changing n within the for loop will have no effect on the next parameter fetched, think about:
@wisecracker. No matter what you assign to n inside the loop, it does not matter, since n is given its next value by the for statement just before printing, but this is off topic and should be in another thread...
I think it was the original Bourne shell. I just tried it on Solaris 10 (where /bin/sh is the classic Bourne Shell):
$ /bin/sh ./t | grep Total
Total Programs 0
Total Lines 0
$ /usr/xpg4/bin/sh ./t | grep Total
Total Programs 50
Total Lines 787310
$ bash ./t | grep Total
Total Programs 50
Total Lines 787310
$ ksh ./t | grep Total
Total Programs 50
Total Lines 787310
So apparently the Bourne Shell is using a subshell for a while loop even when only redirecting input..
SCO ships with 3 Bourne Shells.
/u95/bin/sh which is aware of files larger than 2gb
/usr/bin/posix/sh which I never knew about.
/bin/sh which is the default shell when creating new users and is the only one that displays this problem.
Interesting. So this basic, fundamental behavior which most everyone would depend on today is not fundamental Bourne behavior! It's probably POSIX but not old-fashioned, bug-compatible-with-1970 Bourne.
This is an interesting example. It shows that pure Bourne shells execute while loops in a subshell environment when the input to that loop is redirected from a file, but does not create a subshell when the input is the script's standard input. If I knew that Bourne shell "feature", I had forgotten it.
Right. I always thought this to be one of the definitive advantages of ksh (at least for scripting) over all the other shells, because with "print -u" and "read -u" you can easily put all the I/O-descriptors to work. In Bourne-shell as well as in bash this was always a hassle. Picture the equivalent like:
in bash. It is not impossible, but the code would be a lot less clean. In addition you'd need different redirections (one overwriting, one appending) for the two lines going to file.1.