How do I check if a variable exists in an 'if' statement?

I need to check a variable’s existence in an if statement. Something to the effect of:

if [ -v $somevar ]
then
    echo "Variable somevar exists!"
else
    echo "Variable somevar does not exist!"

And the closest question to that was this, which doesn’t actually answer my question.

Asked By: user104976

||

As mentioned in the answer on SO, here is a way to check:

if [ -z ${somevar+x} ]; then echo "somevar is unset"; else echo "somevar is set to '$somevar'"; fi

where ${somevar+x} is a parameter expansion which evaluates to the null if var is unset and substitutes the string “x” otherwise.

Using -n, as suggested by the other answer, will only check if the variable contains empty string. It will not check its existence.

Answered By: shivams

In modern bash (version 4.2 and above):

[[ -v name_of_var ]]

From help test:

-v VAR, True if the shell variable VAR is set

Answered By: Chris Down

POSIXly:

! (: "${somevar?}") 2>/dev/null && echo somevar unset

or you can let your shell show the message for you:

(: "${somevar?}")
zsh: somevar: parameter not set
Answered By: cuonglm

You can’t use if command to check the existence of declared variables in bash however -v option exists in newer bash, but it’s not portable and you can’t use it in older bash versions. Because when you are using a variable if it doesn’t exists it will born at the same time.

E.g. Imagine that I didn’t use or assign a value to the MYTEST variable, but when you are using echo command it shows you nothing! Or if you are using if [ -z $MYTEST ] it returned zero value!
It didn’t return another exit status, which tells you that this variable doesn’t exist!

Now you have two solutions (Without -v option):

  1. Using declare command.
  2. Using set command.

For example:

MYTEST=2
set | grep MYTEST
declare | grep MYTEST

But unfortunately these commands shows you loaded functions in memory too! You can use declare -p | grep -q MYTEST ; echo $? command for cleaner result.

Answered By: Sepahrad Salour
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi
Answered By: Mel
printf ${var+'$var exists!n'}

…will print nothing at all when it doesn’t. Or…

printf $"var does%${var+.}s exist%cn"  not !

…will tell you either way.

you can use the return value of a test to dynamically expand to the appropriate format string for your condition:

[ "${var+1}" ]
printf $"var does%.$?0s exist%cn"  not !

You can also make printf fail based on a substitution…

printf $"var does%${var+.}s exist%cn%.${var+b}d" 
         not ! \c >&"$((2${var+-1}))" 2>/dev/null

…which prints $var does not exist! to stderr and returns other than 0 when $var is unset, but prints $var does exist! to stdout and returns 0 when $var is set.

Answered By: mikeserv

This simple line works (and works on most POSIX shells):

${var+"false"} && echo "var is unset"

Or, written in a longer form:

unset var

if ${var+"false"}
then
   echo "var is unset"
fi

The expansion is:

  • If the var has a value (even null), false is replaced
  • If the var has “no value”, then “no value” (null) is replaced.

The ${var+"false"} expansion expands to either “null” of “false”.
Then, “nothing” or the “false” is executed, and the exit code set.

There is no need to call the command test ([ or [[) as the exit value is set by the (execution of) the expansion itself.

Answered By: user79743

Depends what you mean by exists.

Does a variable that has been declared but not assigned exist?

Does an array (or hash) variable that has been assigned an empty list exist?

Does a nameref variable pointing to a variable that currently isn’t assigned exist?

Do you consider $-, $#, $1 variables? (POSIX doesn’t).

In Bourne-like shells, the canonical way is:

if [ -n "${var+set}" ]; then
  echo '$var was set'
fi

That works for scalar variables and other parameters to tell if a variable has been assigned a value (empty or not, automatically, from the environment, assigments, read, for or other).

For shells that have a typeset or declare command, that would not report as set the variables that have been declared but not assigned (note that in zsh, declaring a variable assigns a value, a default one if not specified).

For shells that support arrays, except for yash and zsh that would not report as set array variables unless the element of indice 0 has been set.

For bash (but not ksh93 nor zsh), for variables of type associative array, that would not report them as set unless their element of key "0" has been set.

For ksh93 and bash, for variables of type nameref, that only returns true if the variable referenced by the nameref is itself considered set.

For ksh, zsh and bash, a potentially better approach could be:

if ((${#var[@]})); then
  echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi

For ksh93, zsh and bash 4.4 or above, there’s also:

if typeset -p var 2> /dev/null | grep -q '^'; then
  echo '$var exists'
fi

Which will report variables that have been set or declared.

Answered By: Stéphane Chazelas

Function to check if variable is declared/unset

including empty $array=()

In addition to @Gilles’s answer

case " ${!foobar*} " in
  *" foobar "*) echo "foobar is declared";;
  *) echo "foobar is not declared";;
esac

— which I did not find a way for to encapsulate it within a function — I’d like to add a simple version, which is partly based on Richard Hansen‘s answer, but does address also the pitfall that occurs with an empty array=():

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • By first testing if the variable is (un)set, the call to declare can be avoided, if not necessary.
  • If however $1 contains the name of an empty $array=(), the call to declare would make sure we get the right result
  • There’s never much data passed to /dev/null as declare is only called if either the variable is unset or an empty array.

With the following code the functions can be tested:

( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
  # do not use this extra parenthesis () in a script!

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}

:;       echo -n 'a;       '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=;      echo -n 'a=;      '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd";  echo -n 'a="sd";  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=();    echo -n 'a=();    '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=("");  echo -n 'a=("");  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:;       echo -n 'a;       '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=;      echo -n 'a=;      '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=();    echo -n 'a=();    '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=("");  echo -n 'a=("");  '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)

The script should return

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset
Answered By: Martin Rüegg

bash function that works for both scalar and array types:

definition

has_declare() { # check if variable is set at all
    local "$@" # inject 'name' argument in local scope
    &>/dev/null declare -p "$name" # return 0 when var is present
}

invocation

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
Answered By: Andrei Pozolotin

The pure shell way:

[ "${var+1}" ] || echo "The variable has not been set"

Test script:

#!/bin/sh
echo "Test 1, var has not yet been created"
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 2, var=1"
var=1
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 3, var="
var=
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 4, unset var"
unset var
[ "${var+1}" ] || echo "The variable has not been set"
echo "Done"

Results:

Test 1, var has not yet been created
The variable has not been set
Test 2, var=1
Test 3, var=
Test 4, unset var
The variable has not been set
Done
Answered By: Andreas Mikael Bank

With bash 4.4.19 the following worked for me. Here is a complete example

$export MAGENTO_DB_HOST="anyvalue"

#!/bin/bash

if [ -z "$MAGENTO_DB_HOST" ]; then
    echo "Magento variable not set"
else
    echo $MAGENTO_DB_HOST
fi
Answered By: Aftab Naveed
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.