Home How to check if a variable is set in Bash?

# How to check if a variable is set in Bash?

prosseek
1#
prosseek Published in 2010-08-30 14:54:38Z
 How do I know if a variable is set in Bash? For example, how do I check if the user gave the first parameter to a function? function a { # if $1 is set ? }  Community 2# Community Reply to 2017-05-23 11:55:03Z # Functions to check if variable is declared/unset ## including empty $array=()

The following functions test if the given name exists as a variable

# 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.

This functions would test as showed in the following conditions:

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


.

### For more details

and a test script see my answer to the question "How do I check if a variable exists in bash?".

Remark: The similar usage of declare -p, as it is also shown by Peregring-lk's answer, is truly coincidental. Otherwise I would of course have credited it!

Paul Creasey
3#
Paul Creasey Reply to 2010-08-30 16:43:46Z
 if [ "$1" != "" ]; then echo \$1 is set else echo \$1 is not set fi  Although for arguments it is normally best to test$#, which is the number of arguments, in my opinion. if [ $# -gt 0 ]; then echo \$1 is set else echo \$1 is not set fi  Steel Brain 4# Steel Brain Reply to 2016-03-07 22:55:45Z  There are many ways to do this with the following being one of them: if [ -z "$1" ]  This succeeds if $1 is null or unset codaddict 5# codaddict Reply to 2010-08-31 07:23:26Z  You can do: function a { if [ ! -z "$1" ]; then echo '$1 is set' fi }  Flow 6# Flow Reply to 2013-10-13 15:42:36Z  To check for non-null/non-zero string variable, i.e. if set, use if [ -n "$1" ]  It's the opposite of -z. I find myself using -n more than -z.
ghostdog74
7#
ghostdog74 Reply to 2010-08-30 15:32:16Z
 case "$1" in "") echo "blank";; *) echo "set" esac  Community 8# Community Reply to 2017-05-23 12:34:53Z  To check whether a variable is set with a non-empty value, use [ -n "$x" ], as others have already indicated. Most of the time, it's a good idea to treat a variable that has an empty value in the same way as a variable that is unset. But you can distinguish the two if you need to: [ -n "${x+set}" ] ("${x+set}" expands to set if x is set and to the empty string if x is unset). To check whether a parameter has been passed, test $#, which is the number of parameters passed to the function (or to the script, when not in a function) (see Paul's answer). chepner 9# chepner Reply to 2012-01-31 22:05:06Z  Read the "Parameter Expansion" section of the bash man page. Parameter expansion doesn't provide a general test for a variable being set, but there are several things you can do to a parameter if it isn't set. For example: function a { first_arg=${1-foo} # rest of the function }  will set first_arg equal to $1 if it is assigned, otherwise it uses the value "foo". If a absolutely must take a single parameter, and no good default exists, you can exit with an error message when no parameter is given: function a { :${1?a must take a single argument} # rest of the function }  (Note the use of : as a null command, which just expands the values of its arguments. We don't want to do anything with $1 in this example, just exit if it isn't set) koola 10# koola Reply to 2012-11-21 11:09:00Z  To check if a var is set or not var=""; [[$var ]] && echo "set" || echo "not set" 
phkoester
11#
phkoester Reply to 2013-05-08 08:32:46Z
 To see if a variable is nonempty, I use if [[ $var ]]; then ... # $var' expands to a nonempty string  The opposite tests if a variable is either unset or empty: if [[ ! $var ]]; then ... # $var' expands to the empty string (set or not)  To see if a variable is set (empty or nonempty), I use if [[ ${var+x} ]]; then ... # var' exists (empty or nonempty) if [[${1+x} ]]; then ... # Parameter 1 exists (empty or nonempty)  The opposite tests if a variable is unset: if [[ ! ${var+x} ]]; then ... # var' is not set at all if [[ !${1+x} ]]; then ... # We were called with no arguments 
user1857592
12#
user1857592 Reply to 2013-05-25 20:08:04Z
 If you wish to test that a variable is bound or unbound, this works well, even after you've turned on the nounset option: set -o noun set if printenv variableName >/dev/null; then # variable is bound to a value else # variable is unbound fi 
Mr. Polywhirl
13#
Mr. Polywhirl Reply to 2016-08-11 17:19:35Z
 Here's how to test whether a parameter is unset, or empty ("Null") or set with a value: +--------------------+----------------------+-----------------+-----------------+ | | parameter | parameter | parameter | | | Set and Not Null | Set But Null | Unset | +--------------------+----------------------+-----------------+-----------------+ | ${parameter:-word} | substitute parameter | substitute word | substitute word | |${parameter-word} | substitute parameter | substitute null | substitute word | | ${parameter:=word} | substitute parameter | assign word | assign word | |${parameter=word} | substitute parameter | substitute null | assign word | | ${parameter:?word} | substitute parameter | error, exit | error, exit | |${parameter?word} | substitute parameter | substitute null | error, exit | | ${parameter:+word} | substitute word | substitute null | substitute null | |${parameter+word} | substitute word | substitute word | substitute null | +--------------------+----------------------+-----------------+-----------------+  Source: POSIX: Parameter Expansion: In all cases shown with "substitute", the expression is replaced with the value shown. In all cases shown with "assign", parameter is assigned that value, which also replaces the expression.
solidsnack
14#
solidsnack Reply to 2013-06-30 05:22:39Z
 if [[ ${1:+isset} ]] then echo "It was set and not null." >&2 else echo "It was not set or it was null." >&2 fi if [[${1+isset} ]] then echo "It was set but might be null." >&2 else echo "It was was not set." >&2 fi 
Palec
15#
Palec Reply to 2017-03-11 19:46:43Z
 While most of the techniques stated here are correct, bash 4.2 supports an actual test for the presence of a variable (man bash), rather than testing the value of the variable. [[ -v foo ]]; echo $? # 1 foo=bar [[ -v foo ]]; echo$? # 0 foo="" [[ -v foo ]]; echo $? # 0  Peter Mortensen 16# Peter Mortensen Reply to 2015-11-10 16:02:25Z  On a modern version of Bash (4.2 or later I think; I don't know for sure), I would try this: if [ ! -v SOMEVARIABLE ] #note the lack of a$ sigil then echo "Variable is unset" elif [ -z "$SOMEVARIABLE" ] then echo "Variable is set to an empty string" else echo "Variable is set to some string" fi  Peter Mortensen 17# Peter Mortensen Reply to 2015-11-10 16:03:35Z  I always use this one, based on the fact that it seems easy to be understood by anybody who sees the code for the very first time: if [ "$variable" = "" ] then echo "Variable X is empty" fi  And, if wanting to check if not empty; if [ ! "$variable" = "" ] then echo "Variable X is not empty" fi  That's it. Community 18# Community Reply to 2017-05-23 12:18:27Z  The answers above do not work when Bash option set -u is enabled. Also, they are not dynamic, e.g., how to test is variable with name "dummy" is defined? Try this: is_var_defined() { if [$# -ne 1 ] then echo "Expected exactly one argument: variable name as string, e.g., 'my_var'" exit 1 fi # Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable # is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value # substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the # operator ':-', but here we leave it blank for empty (null) string. Finally, we need to # substitute the text from $1 as 'var'. This is not allowed directly in Bash with this # construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator. # Example:$1="var" # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]" # Code execute: [ ! -z${var:-} ] eval "[ ! -z \${$1:-} ]" return $? # Pedantic. }  Related: In Bash, how do I test if a variable is defined in "-u" mode Zlatan 19# Zlatan Reply to 2013-12-27 16:30:37Z  I found a (much) better code to do this if you want to check for anything in $@. if [[ $1 = "" ]] then echo '$1 is blank' else echo '$1 is filled up' fi  Why this all? Everything in $@ exists in Bash, but by default it's blank, so test -z and test -n couldn't help you. Update: You can also count number of characters in a parameters. if [ ${#1} = 0 ] then echo '$1 is blank' else echo '$1 is filled up' fi  Steven Penny 20# Steven Penny Reply to 2014-05-11 05:43:17Z  [[$foo ]]  Or (( ${#foo} ))  Or let${#foo}  Or declare -p foo 
Peter Mortensen
21#
Peter Mortensen Reply to 2015-11-10 16:04:12Z
 In a shell you can use the -z operator which is True if the length of string is zero. A simple one-liner to set default MY_VAR if it's not set, otherwise optionally you can display the message: [[ -z "$MY_VAR" ]] && MY_VAR="default" [[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set." 
Peregring-lk
22#
Peregring-lk Reply to 2014-10-18 22:09:55Z
 Using [[ -z "$var" ]] is the easiest way to know if a variable was set or not, but that option -z doesn't distinguishes between a unset variable, and a variable set to an empty string:  set=''$ [[ -z "$set" ]] && echo "Set" || echo "Unset" Unset$ [[ -z "$unset" ]] && echo "Set" || echo "Unset" Unset  It's best to check it according to the type of variable: env variable, parameter or regular variable. For a env variable: [[$(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"  For a parameter (for example, to check existence of parameter "$5": [[$# -ge 5 ]] && echo "Set" || echo "Unset"  For a regular variable (using an auxiliar function, to do it in an elegant way): function declare_var { declare -p "$1" &> /dev/null return$? } declare_var "var_name" && echo "Set" || echo "Unset"  Notes: $# says you the number of positional parameters. declare -p gives you the definition of the variable passed as parameter. If it exists, returns 0, if not, returns 1 and prints an error message.$? gives you the status code of the last executed command. 
Peter Mortensen
23#
Peter Mortensen Reply to 2015-11-10 16:05:00Z
 My prefered way is this: $var=10$if ! ${var+false};then echo "is set";else echo "NOT set";fi is set$unset var $if !${var+false};then echo "is set";else echo "NOT set";fi NOT set  So basically, if a variable is set, it becomes "a negation of the resulting false" (what will be true = "is set"). And, if it is unset, it will become "a negation of the resulting true" (as the empty result evaluates to true) (so will end as being false = "NOT set").
Peter Mortensen
24#
Peter Mortensen Reply to 2015-11-10 16:06:00Z
 This is what I use every day: # # Check if a variable is set # param1 name of the variable # function is_set() { [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")" }  This works well under Linux and Solaris down to bash 3.0. bash-3.00$myvar="TEST" bash-3.00$ is_set myvar ; echo $? 0 bash-3.00$ mavar="" bash-3.00$is_set myvar ; echo$? 0 bash-3.00$unset myvar bash-3.00$ is_set myvar ; echo $? 1  Keith Thompson 25# Keith Thompson Reply to 2015-08-12 18:43:56Z  if [[${!xx[@]} ]] ; then echo xx is defined; fi 
AlejandroVD
26#
AlejandroVD Reply to 2016-03-28 21:13:34Z
 In bash you can use -v inside the [[ ]] builtin: #! /bin/bash -u if [[ ! -v SOMEVAR ]]; then SOMEVAR='hello' fi echo $SOMEVAR  Mark Haferkamp 27# Mark Haferkamp Reply to 2016-02-15 14:32:17Z  If var can be an array, then [ -z "${var+x}" ] parameter substitution is incorrect. To be really sure in Bash you need to use array syntax like [ "${#var[@]}" = 0 ], as shown below. is-var-set () { results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}" if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then echo -e "$1: var's unset.\t$results" elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then echo -e "$1: var is set. \t$results" else echo -e "$1: Is var set? \t$results" fi unset var # so we don't have to do it everywhere else }  In almost all cases, they agree. The only situation I've found where the array method is more accurate is when the variable is a non-empty array with position 0 unset (e.g., in tests 7 and A below). This disagreement comes from $var being shorthand for ${var[0]}, so [ -z "${var+x}" ] isn't checking the whole array. Here are my test cases. unset var; is-var-set 1 # var unset var=''; is-var-set 2 # var[0] set to '' var=foo; is-var-set 3 # var[0] set to 'foo' var=(); is-var-set 4 # var unset (all indices) var=(foo); is-var-set 5 # var[0] set to 'foo' var=([0]=foo); is-var-set 6 # var[0] set to 'foo' var=([1]=foo); is-var-set 7 # var[0] unset, but var[1] set to 'foo' declare -a var; is-var-set 8 # var empty, but declared as an array declare -A var; is-var-set 9 # var empty, but declared as an associative array declare -A var # Because is-var-set() conveniently unsets it var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var's otherwise empty declare -a var # Demonstrate that Bash knows about var, even when there's declare -A var; is-var-set B # apparently no way to just _check_ its existence  Here's the output. 1: var's unset. ${var+x}=${#var[@]}=0 2: var is set. ${var+x}=x${#var[@]}=1 3: var is set. ${var+x}=x${#var[@]}=1 4: var's unset. ${var+x}=${#var[@]}=0 5: var is set. ${var+x}=x${#var[@]}=1 6: var is set. ${var+x}=x${#var[@]}=1 7: Is var set? ${var+x}=${#var[@]}=1 8: var's unset. ${var+x}=${#var[@]}=0 9: var's unset. ${var+x}=${#var[@]}=0 A: Is var set? ${var+x}=${#var[@]}=1 ./foo.sh: line 26: declare: var: cannot convert indexed to associative array B: var's unset. ${var+x}=${#var[@]}=0  In sum: ${var+x} parameter expansion syntax works just as well as ${#var[@]} array syntax in most cases, such as checking parameters to functions. The only way this case could break is if a future version of Bash adds a way to pass arrays to functions without converting contents to individual arguments. Array syntax is required for non-empty arrays (associative or not) with element 0 unset. Neither syntax explains what's going on if declare -a var has been used without assigning even a null value somewhere in the array. Bash still distinguishes the case somewhere (as seen in test B above), so this answer's not foolproof. Fortunately Bash converts exported environment variables into strings when running a program/script, so any issues with declared-but-unset variables will be contained to a single script, at least if it's not sourcing other scripts.
Daniel S
28#
Daniel S Reply to 2016-03-01 13:23:29Z
 I like auxiliary functions to hide the crude details of bash. In this case, doing so adds even more (hidden) crudeness: # The first ! negates the result (can't use -n to achieve this) # the second ! expands the content of varname (can't do ${$varname}) function IsDeclared_Tricky { local varname="$1" ! [ -z${!varname+x} ] }  Because I first had bugs in this implementation (inspired by the answers of Jens and Lionel), I came up with a different solution: # Ask for the properties of the variable - fails if not declared function IsDeclared() { declare -p $1 &>/dev/null }  I find it to be more straight-forward, more bashy and easier to understand/remember. Test case shows it is equivalent: function main() { declare -i xyz local foo local bar= local baz='' IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz:$?" IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?" IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar:$?" IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?" IsDeclared xyz; echo "IsDeclared xyz:$?" IsDeclared foo; echo "IsDeclared foo: $?" IsDeclared bar; echo "IsDeclared bar:$?" IsDeclared baz; echo "IsDeclared baz: $?" } main  The test case also shows that local var does NOT declare var (unless followed by '='). For quite some time I thought i declared variables this way, just to discover now that i merely expressed my intention... It's a no-op, i guess. IsDeclared_Tricky xyz: 1 IsDeclared_Tricky foo: 1 IsDeclared_Tricky bar: 0 IsDeclared_Tricky baz: 0 IsDeclared xyz: 1 IsDeclared foo: 1 IsDeclared bar: 0 IsDeclared baz: 0 BONUS: usecase I mostly use this test to give (and return) parameters to functions in a somewhat "elegant" and safe way (almost resembling an interface...): #auxiliary functions function die() { echo "Error:$1"; exit 1 } function assertVariableDeclared() { IsDeclared "$1" || die "variable not declared:$1" } function expectVariables() { while (( $# > 0 )); do assertVariableDeclared$1; shift done } # actual example function exampleFunction() { expectVariables inputStr outputStr outputStr="$inputStr world!" } function bonus() { local inputStr='Hello' local outputStr= # remove this to trigger error exampleFunction echo$outputStr } bonus  If called with all requires variables declared: Hello world! else: Error: variable not declared: outputStr
ecerulm
29#
ecerulm Reply to 2016-11-16 11:26:13Z
 For those that are looking to check for unset or empty when in a script with set -u: if [ -z "${var-}" ]; then echo "Must provide var environment variable. Exiting...." exit 1 fi  The regular [ -z "$var" ] check will fail with var; unbound variable if set -u but [ -z "${var-}" ] expands to empty string if var is unset without failing. Jarrod Chesney 30# Jarrod Chesney Reply to 2016-12-16 04:46:12Z ## You want to exit if it's unset This worked for me. I wanted my script to exit with an error message if a parameter wasn't set. #!/usr/bin/env bash set -o errexit # Get the value and empty validation check all in one VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"


This returns with an error when it's run

peek@peek:~$./setver.sh ./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument  ## Check only, no exit - Empty and Unset are INVALID Try this option if you just want to check if the value set=VALID or unset/empty=INVALID. TSET="good val" TEMPTY="" unset TUNSET if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi # INVALID if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID


Or, Even short tests ;-)

[ "${TSET:-}" ] && echo "VALID" || echo "INVALID" [ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"  ## Check only, no exit - Only empty is INVALID And this is the answer to the question. Use this if you just want to check if the value set/empty=VALID or unset=INVALID. NOTE, the "1" in "..-1}" is insignificant, it can be anything (like x) TSET="good val" TEMPTY="" unset TUNSET if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi # VALID if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID


Short tests

[ "${TSET+1}" ] && echo "VALID" || echo "INVALID" [ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "\${TUNSET+1}" ] && echo "VALID" || echo "INVALID"


I dedicate this answer to @mklement0 (comments) who challenged me to answer the question accurately.

Reference http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

 You need to login account before you can post.
Processed in 0.424198 second(s) , Gzip On .