Two function definitions, the only difference is that the first combines the local
storage keyword with the assignment, while the second separates them:
function foo {
local fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
echo $?
}
function bar {
local fn
fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
echo $?
}
foo
bar
This echoes "0" then "1". I expect it to echo "1" then "1". It seems like the value of $?
is the result of the assignment to local, rather than the result of the command substitution.
Why does bash 4.2.46(1)-release behave this way?
Best Answer
I thought this behavior was documented explicitly, because it's such a gotcha (especially when running bash scripts with
-o errexit
!), but it doesn't seem to. My copy of the manual says the following (aboutglobal
, which behaves the same aslocal
when within a function):So it would appear that
local
is not a keyword in the sense that one would expect in other programming languages: when an assignment-like parameter is provided tolocal
, that does not qualify the initialization; rather, thelocal
built-in command takes care of making the assignment happen, and the return code is that oflocal
itself, not of the code possibly run in the initializer, and that return code will only be non-zero in the list of conditions listed above.To perhaps answer the question in a more literal sense, as bishop mentioned in a comment, bash maintainer Chet Ramey was once asked if he would consider making
local
reflect failures happening during assignment, and responded, in essence, that assigning is notlocal
's main mission:It may be worth noting that the same behavior can also be observed in the
zsh
shell.The solution is to separate the two operations: