bash locals are eager to please – they always return 0.

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.

Advertisements
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s