How do I determine whether a variable is already defined? Or a function?

There are several ways to test these things, depending on the exact requirements. Most of the time, the desired test is whether a variable has a non-empty value. In this case, we may simply use:

if test "$var"; then
  echo "The variable has a non-empty value."

If this fails for you because you use set -u, please see FAQ 112.

If we wish to distinguish between an empty variable and an unset variable, then we may use the + parameter expansion:

if test "${var+defined}"; then
  echo "The variable is defined."

The magic here is the +, not the word defined. We can use any non-empty word after the + sign. I prefer defined because it indicates what kind of test is being performed.

Some people prefer the -v option that was added in bash 4.2:

# Bash 4.2 and up
# Bash 4.3 if you want to test an array element
if test -v var; then
  echo "The variable is defined."

There's really no benefit to this over the portable test, though.

Setting a default value

If what we really want is to set a variable to a default value unless it already has a value, then we may skip the test, and use the = parameter expansion:

: "${var=default}"

See FAQ 73 for details.

Testing whether a function has been defined

For determining whether a function with a given name is already defined, there are several answers, all of which require Bash (or at least, non-Bourne) commands. Testing that a function is defined should rarely be necessary. Just define the function as you want it to be defined instead of worrying about what might or might not have been inherited from who-knows-where.

declare -F f >/dev/null       # Bash only - declare outputs "f" and returns 0 if defined, returns non-zero otherwise.
typeset -f f >/dev/null       # Bash/Ksh - typeset outputs the entire function and returns 0 if defined, returns non-zero otherwise.
[[ $(type -t f) = function ]] # Bash-only - "type" outputs "function" if defined. In ksh (and mksh), the "type" alias for "whence -v" differs.

# Bash/Ksh. Workaround for the above, but the first two are preferable.
isFunction() [[ $(type ${BASH_VERSION:+-t} "$1") == ${KSH_VERSION:+"$1 is a "}function ]]; isFunction f

BashFAQ/083 (last edited 2018-08-13 18:39:06 by GreyCat)