Today I was surprised by the behaviour of local. Consider the following script:
#!/bin/bash set -ue set -o pipefail declare -i foo=$(ls non_existant_file | wc -l) echo foo is "$foo"
That actually runs to completion, prints “foo is 0”, and returns 0. Turns out the problem is that local always returns 0 (according to the manpage). So it seems to me that what we want is to separate the declaration and the assignment:
#!/bin/bash set -ue set -o pipefail declare -i foo foo=$(ls non_existant_file | wc -l) echo foo is "$foo"
This causes the script to exit (and return non-zero) before reaching the echo.
ShellCheck does not catch this issue. To avoid this pitfall, we might propose to always separate declaration and assignment for any non-trivial assignments. A consequence of this guidelines is that for non-trivial assignments we cannot take advantage of the readonly flag, but I think that’s less important than catching broken assignments that should have triggered errexit.