difference between unset and empty variables in bash

Unset (non-existant) variables and empty variables behaves differently in parameter expansion:

In the following examples:
Without colon:

Checks only for variable existence.

With colon:

Checks for variable existence, if it exists, make sure that it's not empty.
In other words, checks both for variable existence and non-emptiness.


  • ${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

  • ${parameter-word}
    If parameter is unset...


  • ${parameter:=word}
    If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional parameters and special parameters may not be assigned to in this way.

  • ${parameter=word}
    If parameter is unset...


  • ${parameter:?word}
    If parameter is unset or null, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

  • ${parameter?word}
    If parameter is unset...


  • ${parameter:+word}
    If parameter is unset or null, nothing is substituted, otherwise the expansion of word is substituted.

  • ${parameter+word}
    If parameter is unset...


Source


You can test with

[ -v name ]

name is without $ sign


${var+set} substitutes nothing if the variable is unset and set if it is set to anything including the empty string. ${var:+set} substitutes set only if the variable is set to a non-empty string. You can use this to test for either case:

if [ "${foo+set}" = set ]; then
    # set, but may be empty
fi

if [ "${foo:+set}" = set ]; then
    # set and nonempty
fi

if [ "${foo-unset}" = unset ]; then
    # foo not set or foo contains the actual string 'unset'
    # to avoid a potential false condition in the latter case,
    # use [ "${foo+set}" != set ] instead
fi

if [ "${foo:-unset}" = unset ]; then
    # foo not set or foo empty or foo contains the actual string 'unset'
fi

Tags:

Bash