This question already has an answer here:
Given the following bash script:
#!/usr/bin/env bash
echo $BASH_VERSION
# local [option] [name[=value] ... | - ]
# For each argument, a local variable named name is created, and assigned value. The option can be any
# of the options accepted by declare. When local is used within a function, it causes the variable name
# to have a visible scope restricted to that function and its children. If name is -, the set of shell
# options is made local to the function in which local is invoked: shell options changed using the set
# builtin inside the function are restored to their original values when the function returns. With no
# operands, local writes a list of local variables to the standard output. It is an error to use local
# when not within a function. The return status is 0 unless local is used outside a function, an invalid
# name is supplied, or name is a readonly variable.
function __count_words {
local feedback=$(echo "app1 app2")
echo $feedback
return $(IFS=' ' set -- ${feedback} && echo $#)
}
function invoke_func {
declare -f $1_${DF_SYSTEM} >/dev/null
[ $? -eq 0 ] && { $1_${DF_SYSTEM}; return $?; } || { $1; return $?; }
}
function check_words {
local list=$(invoke_func __count_words)
local count=$?
echo "V1: XXXX [c=$count] > $list"
list2=$(invoke_func __count_words)
local count2=$?
echo "V2: XXXX [c=$count2] > $list2"
}
check_words
The output is:
4.4.12(1)-release
V1: XXXX [c=0] > app1 app2
V2: XXXX [c=2] > app1 app2
What is the rationale behind the decision to make a seemingly similar assignment syntax different with regard to return values? I reckon I found the relevant section of the bash(1) man page, however it is unclear as to why this was done that way.
In the case of the local variable assignment, the return status is always 0, however with the global assignment, the return status varies depending on the return status of the called function inside the assignment.
This is an issue that Shellcheck detects as SC2155; consider reading the linked wiki page (and, perhaps, running your code through Shellcheck before asking about it here in the future).
A best-practices implementation of your
check_words
function would look like this, and does not exhibit your issue:The
local
keyword is a built-in command. Like other commands, it has an exit status. Thus, that exit status overrides any exit status from a command substitution used to derive a value.(Also, the
function
keyword makes your code gratuitously incompatible with POSIX sh, while not adding any compensating advantages; it's best avoided in favor of POSIX-compliant function declaration syntax).