16

Using bash, what's the best method to check if a variable is empty or not?

If I use:

if [ -z "$VAR" ]

as suggested in a forum this works for an unset variable but it is true when the variable is set but empty. Suggestions?

6 Answers 6

50

${var+set} substitutes nothing if the variable is unset and set if it is set to anything including the empty string. ${var:+set} substitutes set only if the variable is set to a non-empty string. You can use this to test for either case:

if [ "${foo+set}" = set ]; then
    # set, but may be empty
fi

if [ "${foo:+set}" = set ]; then
    # set and nonempty
fi

if [ "${foo-unset}" = unset ]; then
    # foo not set or foo contains the actual string 'unset'
    # to avoid a potential false condition in the latter case,
    # use [ "${foo+set}" != set ] instead
fi

if [ "${foo:-unset}" = unset ]; then
    # foo not set or foo empty or foo contains the actual string 'unset'
fi
Sign up to request clarification or add additional context in comments.

3 Comments

just to round out this answer you might add that - works the opposite way, i.e., ${foo-unset} yields 'unset' if foo is unset. this is useful for dry running scripts, e.g. rsync -avuz ${DRYRUN---dry-run} $HOME/blog/ webserver:blog/ which must be run as DRYRUN= upblog.sh to actually perform the upload.
This should be the accepted answer. Edited answer to include @jcomeau_ictx's excellent comment.
This is the best thing ever! You deserve 10000 upvotes @geekosaur
5

You can test with

[ -v name ]

name is without $ sign

3 Comments

I can't find this in either Bash v3.2.57(1) or v4.1.5(1). Which shell is this for?
my bash shell version is 4.3 in ubuntu 15.10. check with "help test" command whether "-v" operator exist. actually there is two test commands one is shell builtin and the other is /usr/bin/test
Since -v is not supported by POSIX, use [[ ... ]] rather than [...].
4

Unset (non-existant) variables and empty variables behaves differently in parameter expansion:

In the following examples:
Without colon:

Checks only for variable existence.

With colon:

Checks for variable existence, if it exists, make sure that it's not empty.
In other words, checks both for variable existence and non-emptiness.


  • ${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

  • ${parameter-word}
    If parameter is unset...


  • ${parameter:=word}
    If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional parameters and special parameters may not be assigned to in this way.

  • ${parameter=word}
    If parameter is unset...


  • ${parameter:?word}
    If parameter is unset or null, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

  • ${parameter?word}
    If parameter is unset...


  • ${parameter:+word}
    If parameter is unset or null, nothing is substituted, otherwise the expansion of word is substituted.

  • ${parameter+word}
    If parameter is unset...


Source

Comments

0

well, here's one way

$ s=""
$ declare -p s
declare -- s=""
$ unset s
$ declare -p s
bash: declare: s: not found

an error message will occur if the variable is unset.

2 Comments

The original question was how to distinguish between variables that are set to the empty string versus variables that are not set at all. This returns blank for both cases.
@KevinBeck, eh? declare -- s="" is not an empty string, so it doesn't "return blank" in that case; and anyhow, you can just check exit status: if declare -p s &>/dev/null; then echo "Variable s is set"; else echo "Variable s is unset"; fi. I'm not upvoting this because there are better choices (more portable, easier-to-read); but it certainly does work.
-2
if [ `set | grep '^VAR=$'` ]

This searches for the string "VAR=" in the list of variables set.

4 Comments

I don't know who vote you down, but your solution works to me!
I answered the wrong question the first time. Here is a corrected answer.
My downvote is because this is unidiomatic, clumsy, and inefficient. The shell has built-in functionality for this; in addition, you have a useless use of backticks and apparently an incomplete understanding of what the if statement does.
If you're going to use this approach, it should at least be changed to if set | grep -q '^VAR=$'; then ...
-3

This would be true only for empty, not unset (or has value)

[ -z ${VAR-X}

2 Comments

Welcome to stackoverflow. Please elaborate a bit more on how this approach works than the accepted answer.
This is simply buggy. It needs quotes around the expansion and a closing ] (or a change from [ to test) to function correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.