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 (about
global
, which behaves the same as local
when within a function):
The return status is zero unless an invalid option is encountered,
an attempt is made to define a function using ‘-f foo=bar’, an
attempt is made to assign a value to a readonly variable, an attempt
is made to assign a value to an array variable without using the
compound assignment syntax [...], one of the names is not a
valid shell variable name, an attempt is made to turn off readonly
status for a readonly variable, an attempt is made to turn off array
status for an array variable, or an attempt is made to display a
non-existent function with -f.
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 to local
, that does not qualify the
initialization; rather, the local
built-in command takes care of
making the assignment happen, and the return code is that of local
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 not
local
's main
mission:
Because that's not what local and its siblings [...] do. These
builtins exist to assign and modify variable attributes. As an
added feature, they support value assignment at the same time, but
the important function is the attribute setting. They don't need to
know how the value was computed. [...] Since the function is setting
the attribute or value, the exit status should reflect whether or
not that succeeded.
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:
local variable
variable=$( somecommand )
exit_status=$?
local
in ZSH also behaves this way) – thrig Feb 07 '17 at 19:32local
built in:The return status is 0 unless local is used outside a function, an invalid name is sup‐ plied, or name is a readonly variable.
Please re-read the manual for your version of bash. It may be there already. – Sergiy Kolodyazhnyy Feb 07 '17 at 22:12