On Fri, 2 Dec 2022 at 20:28, Ulrich Windl <ulrich.wi...@rz.uni-regensburg.de> wrote:
> Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") > "Surprising" is subjective. There is no indication in the manual page that "declare" ignores the exit > code of commands being executed to set values. > Framing this as `declare` "ignoring" something indicates a possible misunderstanding of the separate phases of execution. Every command (with exactly three exceptions) sets its own exit status without regard for any previous value of $?, including any set by $(...) expansions used to create the command in question. If anything is weird, it's that simple (bare) assignments set $? to 0 UNLESS there's a command substitution providing a status. The other two exceptions are `return` and `exit`, which use the previous $? as the default if no parameter is supplied. Like every other command, including "declare", sets its exit status independently of what $? is before it runs. So it's somewhat of a mystery why anyone would expect "declare" to be any different. (Actually, it's no mystery: cargo-cult coding is the norm, as the majority of people writing shell scripts have not read all of "man bash" and have little idea of how the shell is actually supposed to work. So perhaps Bash needs an officially sanctioned "beginners' guide".) Found in the real code (intended to trigger a bug): > declare ERRORS=0 ARGS=$(getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- > "$@") > if [ $? -ne 0 ]; then > usage > fi > That is a well-known anti-pattern that should be avoided. Some working equivalents would be: ``` declare ARGS=$( getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- "$@" ) ERRORS=$? (( ERRORS == 0 )) || usage ``` or: ``` declare ARGS ERRORS=0 ARGS=$( getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- "$@" ) || usage ``` -Martin (PS: "Working" would be questionable, since putting `getopt` in a subshell prevents it from updating "$@"; and `test $? = 0` and its variants are pointless clutter.)