Skip to content
Martin Bagge / brother edited this page May 12, 2020 · 23 revisions

Declare and assign separately to avoid masking return values.

Problematic code in the case of export:

export foo="$(mycmd)"

Correct code:

foo="$(mycmd)"
export foo

Rationale:

In the original code, the return value of mycmd is ignored, and export will instead always return true. This may prevent conditionals, set -e and traps from working correctly.

When first marked for export and assigned separately, the return value of the assignment will be that of mycmd. This avoids the problem.

Exceptions:

If you intend to ignore the return value of an assignment, you can either ignore this warning or use

foo=$(mycmd) || true
export foo

Shellcheck does not warn about export foo=bar because bar is a literal and not a command substitution with an independent return value. It also does not warn about local -r foo=$(cmd), where declaration and assignment must be in the same command.

Problematic code in the case of local:

local foo="$(mycmd)"

Correct code:

local foo
foo=$(mycmd)

Rationale

The exit status of the command is overridden by the exit status of the creation of the local variable. For example:

$ f() { local foo=$(false) || echo foo; }; f
$ f() { local foo; foo=$(false) || echo foo; }; f
foo

Problematic code in the case of readonly:

readonly foo="$(mycmd)"

Correct code:

foo="$(mycmd)"
readonly foo

Word splitting and quoting issue with dash, maybe others

A serious quoting problem with dash is another reason to declare and assign separately. Dash is the default, /bin/sh shell on Ubuntu. More specifically, dash version 0.5.8-2.10 and others cannot run this code:

f(){ local e=$1; }
g(){ local g=$(printf '%s' "foo 2"); }
f "1 2"
g

While this runs fine in other shells, dash doesn't treat this as an assignment and fails like this:

local: 2: bad variable name

The direct workaround to this bug is to quote the right-hand-side of the assignment. Separating declaraction and assignment also makes this runs fine in any shell.

(A rule to catch this problem is in the works at #1556).

ShellCheck

Each individual ShellCheck warning has its own wiki page like SC1000. Use GitHub Wiki's "Pages" feature above to find a specific one, or see Checks.

Clone this wiki locally