Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

What is the best way to determine if a variable in bash contains ""?

I have heard it recommended that I do if [ "x$variable" = "x" ]

Is that the correct way? (there must be something more straightforward)

share|improve this question
6  
You can also ask this on stackoverflow - it's a valid programming question, and will certainly get more eyes than here... –  Adam Davis May 12 '09 at 18:03
add comment

11 Answers

up vote 174 down vote accepted

This will return true if a variable is unset.

if [ -z "$VAR" ];
share|improve this answer
9  
Does that include if a variable IS SET to a value of "" ? –  Brent May 12 '09 at 18:25
4  
Yes it does... "-z" tests for a zero-length string. –  David Z May 13 '09 at 2:40
    
That is true - I was going to recommend -s, but test -s '' exits with a 1, whereas test -z '' gives us the anticipated 0. –  Aaron Newton Sep 1 '12 at 1:37
1  
what's the inverse of -z? if not empty string. –  Pineapple Under the Sea Jul 19 '13 at 23:48
5  
if [ ! -z "$VAR" ]; –  Aaron Copley Jul 22 '13 at 17:26
show 2 more comments

In Bash, when you're not concerned with portability to shells that don't support it, you should always use the double-bracket syntax:

Any of the following:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

In Bash, using double square brackets, the quotes aren't necessary. You can simplify the test for a variable that does contain a value to:

if [[ $variable ]]

This syntax is compatible with zsh and ksh (at least ksh93, anyway). It does not work in pure POSIX or older Bourne shells such as sh or dash.

See my answer here and BashFAQ/031 for more information about the differences between double and single square brackets.

You can test to see if a variable is specifically unset (as distinct from an empty string):

if [[ -z ${variable+x} ]]

where the "x" is arbitrary.

If you want to know whether a variable is null but not unset:

if [[ -z $variable && ${variable+x} ]]
share|improve this answer
1  
That if [[ $variable ]] worked fine for me, and didn't even need the set -u that was required by one of the other proposed solutions. –  Teemu Leisti Sep 14 '12 at 15:14
    
I think this is better than the accepted answer. –  qed Apr 5 '13 at 10:00
add comment

A variable in bash (and any POSIX-compatible shell) can be in one of three states:

  • unset
  • set to the empty string
  • set to a non-empty string

Most of the time you only need to know if a variable is set to a non-empty string, but occasionally it's important to distinguish between unset and set to the empty string.

The following are examples of how you can test the various possibilities, and it works in bash or any POSIX-compatible shell:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Here is the same thing but in handy table form:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

The ${VAR+foo} construct expands to the empty string if VAR is unset or to foo if VAR is set to anything (including the empty string).

The ${VAR-foo} construct expands to the value of VAR if set (including set to the empty string) and foo if unset. This is useful for providing user-overridable defaults (e.g., ${COLOR-red} says to use red unless the variable COLOR has been set to something).

The reason why [ x"${VAR}" = x ] is often recommended for testing whether a variable is either unset or set to the empty string is because some implementations of the [ command (also known as test) are buggy. If VAR is set to something like -n, then some implementations will do the wrong thing when given [ "${VAR}" = "" ] because the first argument to [ is erroneously interpreted as the -n operator, not a string.

share|improve this answer
    
Testing for a variable set to the empty string can also be done using [ -z "${VAR-set}" ]. –  nwellnhof May 17 '13 at 17:56
    
@nwellnhof: Thanks! I updated my answer to use the briefer syntax. –  Richard Hansen May 18 '13 at 18:00
    
What is the difference between the first and last construct? They both correspond to "VAR is either unset or set to a non-empty string". –  Faheem Mitha Jul 22 '13 at 8:53
    
@FaheemMitha: The difference is "empty string" vs. "non-empty string". –  Richard Hansen Jul 22 '13 at 16:51
1  
@RichardHansen: Thanks, that's a useful addition. –  Faheem Mitha Jul 22 '13 at 17:18
show 2 more comments

If you're interested in distinguishing the cases of set-empty versus unset status, look at the -u option for bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true
share|improve this answer
add comment

-z is a the best way.

Another options I've used is to set a variable, but it can be overridden by another variable eg

export PORT=${MY_PORT:-5432}

If the $MY_PORT variable is empty, then PORT gets set to 5432, otherwise PORT is set to the value of MY_PORT. Note the syntax include the colon and dash.

share|improve this answer
    
Accidentally found this today, and it was exactly what I wanted. Thanks! I have to tolerate set -o nounset in some scripts. –  opello Feb 16 '12 at 23:58
add comment

An alternate I've seen to [ -z "$foo" ] is the following, however I'm not sure why people use this method, anyone know?

[ "x${foo}" = "x" ]

Anyway if you're disallowing unset variables (either by set -u or set -o nounset), then you'll run into trouble with both of those methods. There's a simple fix to this:

[ -z "${foo:-}" ]

Note: this will leave your variable undef.

share|improve this answer
    
There's a comment about the alternative to -z at pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. Basically, it isn't meant to be an alternative to -z. Rather, it handles cases where $foo could expand to something beginning with a metacharacter that [ or test would be confused by. Putting an arbitrary non-metacharacter at the beginning eliminates that possibility. –  James Sneeringer Dec 9 '11 at 19:15
add comment

the entire if-then and -z are unnecessary.

[ "$foo" ] && echo "foo is not empty"
[ "$foo" ] || echo "foo is indeed empty"
share|improve this answer
3  
That will fail if foo contains only spaces –  Brian May 20 '10 at 21:16
1  
Will also fail in some shells if foo begins with a dash since it is interpreted as an option. E.g. on solaris ksh, zsh and bash are no problem, sh and /bin/test will fail –  ktf Oct 20 '11 at 7:40
add comment

This is true exactly when $FOO is set and empty:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]
share|improve this answer
add comment

Personally prefer more clear way to check :

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi
share|improve this answer
    
Some shells do not accept the double equal sign. –  Dennis Williamson Feb 25 '12 at 12:19
1  
The question was about bash. I'm using bash. Works well for me. What exactly You are speaking about ? –  Fedir Feb 25 '12 at 13:03
1  
If you're using Bash, you should use double square brackets. My previous comment was a simple statement of fact for those who might read your answer and be using a different shell. –  Dennis Williamson Feb 25 '12 at 15:49
    
single square brackets are ok in this case, please see serverfault.com/questions/52034/… –  Luca Borrione Aug 31 '12 at 19:21
add comment

The question asks how to check if a variable is an empty string and the best answers are already given for that.
But I landed here after a period passed programming in php and what I was actually searching was a check like the empty function in php working in a bash shell.
After reading the answers I realized I was not thinking properly in bash, but anyhow in that moment a function like empty in php would have been soooo handy in my bash code.
As I think this can happen to others, I decided to convert the php empty function in bash

According to the php manual:
a variable is considered empty if it doesn't exist or if its value is one of the following:

  • "" (an empty string)
  • 0 (0 as an integer)
  • 0.0 (0 as a float)
  • "0" (0 as a string)
  • an empty array
  • a variable declared, but without a value

Of course the null and false cases cannot be converted in bash, so they are omitted.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Example of usage:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Demo:
the following snippet:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

outputs:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Having said that in a bash logic the checks on zero in this function can cause side problems imho, anyone using this function should evaluate this risk and maybe decide to cut those checks off leaving only the first one.

share|improve this answer
add comment

oneliner extension of duffbeer703's solution:

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
share|improve this answer
add comment

protected by Chris S Jul 22 '13 at 17:13

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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