Walt Stoneburner's Ramblings

Currating Chaos

Default value for bash argument

Sometimes we see what we want to see. Take this incorrect code fragment, which attempts to get the value of the first parameter passed to a script and store it in ARG1, using the literal string "DefaultValue" if no parameter was provided:

ARG1=${$1:-DefaultValue}

This produces a 'bad substition' error with bash. The question is, why.

We know that it's possible to get defaults this way:

XYZZY=MagicWord
FOO=${XYZZY:-MumbleFrotz} # FOO gets set to "MagicWord"

unset XYZZY
FOO=${XYZZY:-MumbleFrotz} # FOO gets set to "MumbleFrotz"

So, clearly our bash notation of :- is correct for handling defaults. Taking us back to, again, why?

The answer is that we're seeing what we want to see. Look again. Closer.

We can be so used to thinking that the "first argument" to a script is $1 that we treat it that way, as a single token.

But it's not. $ retreives the value. That means the first argument is actually... 1. And it doesn't help that "1" on its own usually means a value, adding to our cognative blindness, but the context of its usage matters. This means:

ARG1=${$1:-DefaultValue}   # wrong
ARG1=${1:-DefaultValue}    # right

The outer $ handles it, just as ${1} would, without the default clause ':-` provided.

As such, the inner $ associated with "$1" is not just unnecessary, but wrong, and due to code writing habits can be visually hard to spot, even when its staring us in the face.