Bash – Safely define an environment variable

bashenvironment-variablesgnuvariable

AFAICT, neither GNU Bash, nor any other relevant package (e.g. GNU coreutils) that is commonly available in GNU/Linux distros, has a ready-made way to define an environment variable such that the attempt will fail, and indicate failure, if the environment variable already exists. Essentially, a "no-clobber" option for variable assignment, with a non-zero exit status on failure.

Shell parameter expansion (aka "parameter substitution") approaches avoid clobbering, but do not report failure:

unset MY_VARIABLE
: ${MY_VARIABLE:='my_value'}
: ${MY_VARIABLE:='this_will_fail_but_will_nevertheless_have_exit_code_0'}
echo $?
0
echo $MY_VARIABLE
my_value

The best workaround I have come up with is to create a function ("safedef") for that purpose:

die() {
    echo -e >&2 "$@"
    exit 1
}

safedef() {
    if [ -v $1 ]; then
        die 'Name conflict. Variable already defined. Will not overwrite it.'
    else
        # Create and assign environment variable
        export $1="${*:2}"
    fi
}

safedef MY_VARIABLE 'my_value'
safedef MY_OTHER_VARIABLE 'my_other_value'
# Etc, etc...

Questions:

  1. Have I overlooked a ready-made way to achieve this, provided by a free software package that is available in some or all mainstream GNU/Linux distros?
  2. Have I overlooked some kind of bug in safedef that means it could well unexpectedly fail to work as intended? (If so, what is the bug, and what might be a better approach?)

Best Answer

In bash I found the following:

unset MY_VARIABLE
: ${MY_VARIABLE='my_value'}
MY_VARIABLE=${MY_VARIABLE:+$( false )}${MY_VARIABLE:-'this_will_fail_with_exit_1'}
echo $?
echo $MY_VARIABLE

This prints:

1
my_value
Related Question