Salamandar
Salamandar

Reputation: 588

Sh leaks variables defined on function call (but not on command call)

Even though bash and sh are provided by the same package on my system, there are differences:

In bash:

$ echo $auie

$ auie=1 ls

$ echo $auie

$ testfn() { : ; }
$ auie=1 testfn
$ echo $auie
# Nothing

auie is defined only for the calls (ls, testfn), and is not leaked into the environment.

In sh:

$ echo $auie

$ auie=1 ls

$ echo $auie

$ testfn() { : ; }
$ auie=1 testfn
$ echo $auie
1

Here, auie is defined for the ls call only, BUT when the function call occurs, it "leaks" into the environment !

Why does sh behave as such ?

Upvotes: 0

Views: 48

Answers (1)

chepner
chepner

Reputation: 530990

Looking at this page of the POSIX spec, it appears that it is left undefined whether the value of auie should persist after the call to testfn returns:

  • If the command name is a function that is not a standard utility implemented as a function, variable assignments shall affect the current execution environment during the execution of the function. It is unspecified:

    • Whether or not the variable assignments persist after the completion of the function

It's not at all clear why bash would choose two different behaviors depending on how it is invoked. My guess is that bash-as-sh preserves backwards compatibility with some other shell (ksh [which does preserve the value] or the original Bourne shell), while bash-proper implements what the author considered "better" behavior.

In a non-exhaustive test, I can confirm that dash and ksh preserve the value, while bash and zsh do not.

% for sh in bash dash ksh zsh; do
for> echo $sh; $sh -c 'testfn () { : ; }; auie=1 testfn; echo $auie;'
for> done
bash

dash
1
ksh
1
zsh

192%

Upvotes: 1

Related Questions