Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
    
If you want to set $somevar to a value/string if variable does not exist: ${somevar:=42}. – Cyrus Jun 25 '15 at 18:49
    
Personally, I tend to check just for emptiness ([ -n "$var" ] or [ ! -z "$var" ]). I think the existence/nonexistence checks are too subtle, and I prefer my code coarse and simple. – PSkocik Dec 1 '15 at 17:12
up vote 23 down vote accepted

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

share|improve this answer
    
Oh wow!! I never knew about this -v option. Great answer :) – shivams Jun 25 '15 at 16:38
    
My man page is silent about this option! I guess this is the proper solution. +1 – Mark Jun 25 '15 at 16:39
1  
Also works with single brackets: [ -v name_of_var ]. – meuh Jun 25 '15 at 16:45
    
Wow, I didn't know that existed! Thanks! – Interesting... Jun 25 '15 at 20:11
    
beware that for hashes and arrays, it returns false unless the variable has an element of key/indice "0". For namerefs, it tests whether the target is defined. It doesn't work for special parameters like $1, $-, $#... – Stéphane Chazelas Dec 1 '15 at 17:33

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.

share|improve this answer
1  
You need to quote $somevar to handle IFS=x. Either that or quote x. – mikeserv Jun 26 '15 at 0:02

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
share|improve this answer
    
@mikeserv: Yeah, of course, there's many way to do it. Firstly, I think I will duplicated it with this. But in this question, the OP want to check only, he didn't claim that he want to exit or report if variable unset, so I came with a check in subshell. – cuonglm Jun 26 '15 at 1:46
2  
Well, i know, but it's precisely because you have to do it in a subshell like that which indicates it might not be the best way to test here - that's a halt action on failure, it doesn't allow for any simple means to handle a failure. Portably even a trap can only work on EXIT. That's all I'm saying - it just doesn't apply as a pass/fail very well. And this isn't me talking either - i've done exactly this before and it took a little comment chat just like this to convince me. So, I just thought I'd pay it forward. – mikeserv Jun 26 '15 at 1:51
1  
@mikeserv: Well, well, it's a good point. I only wonder, does adding that can make the OP confuse with the syntax :) – cuonglm Jun 26 '15 at 2:24
    
Shorter: ${var+:} echo var unset. – BinaryZebra Nov 30 '15 at 23:11
printf ${var+'$var exists!\n'}

...will print nothing at all when it doesn't. Or...

printf $"var does%${var+.}s exist%c\n" \ 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%c\n" \ not !

You can also make printf fail based on a substitution...

printf $"var does%${var+.}s exist%c\n%.${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.

share|improve this answer

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.

share|improve this answer
    
Yes, except in some old versions of zsh in sh emulation when $IFS contains f, a, l, s or e. Like for other answers, there's the case of arrays, hashes, or other types of variables which one may want to mention. – Stéphane Chazelas Dec 1 '15 at 21:00

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 except in zsh.

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 and zsh, there's also:

if typeset -p var > /dev/null 2>&1; then
  echo '$var exists'
fi

Which will report variables that have been set or declared.

share|improve this answer
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi
share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.