337

How can I check if a variable is empty in Bash?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tree
  • 9,532
  • 24
  • 64
  • 83
  • 1
    http://serverfault.com/questions/7503/how-to-determine-if-a-bash-variable-is-empty – Ciro Santilli OurBigBook.com Jun 28 '16 at 21:20
  • Possible duplicate of [How to check if a variable is set in Bash?](https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash) – codeforester Jul 11 '18 at 20:30
  • 1
    Related post: [Test for non-zero length string in Bash: -n “$var” vs “$var”](https://stackoverflow.com/a/49825114/6862601). – codeforester Jul 11 '18 at 20:35
  • 1
    The true/false table in [Test for non-zero length string in Bash: -n “$var” vs “$var”.](https://stackoverflow.com/a/3870055/246801) post that @codeforester points to is **absolutely fabulous** in showing _how_ you use `-n` and `-z` (their context) really matters, and that with the shell scripting languages their are any number of (seemingly subtle) gotchas to be aware of. – Zach Young Jul 15 '22 at 20:55

10 Answers10

500

In Bash at least the following command tests if $var is empty:

if [[ -z "$var" ]]; then
   # $var is empty, do what you want
fi

The command man test is your friend.

alper
  • 2,919
  • 9
  • 53
  • 102
Jay
  • 13,803
  • 4
  • 42
  • 69
  • 77
    double square brackets are useless here. it may be simple [ -z "$var" ] or even easier imho if test -z "var" .. anyway +1 :) – Luca Borrione Aug 31 '12 at 20:15
  • 2
    double square brackets are not useless, if I do not inlcude I ma getting `./test.ksh[8]: test: argument expected` dunnot the reason but single bracket didn't work but the double one had it. – gahlot.jaggs Oct 04 '13 at 07:24
  • 11
    @LucaBorrione I think you mean `if test -z "$var"`, right? – neu242 Feb 20 '14 at 07:28
  • 1
    Just an added comment for a specific situation not directly mentioned in the question: if the variable is unset and the `set -u` option has been activated, this test will fail with `unbound variable`. In this case, you might prefer @alexli's solution. – anol May 26 '15 at 16:34
  • 3
    @LucaBorrione Just as a late side note: "[[" can be seen as "never useless"; as using "[[" has some advantages over "[" (see http://stackoverflow.com/questions/669452/is-preferable-over-in-bash-scripts for example) – GhostCat Jun 01 '15 at 08:06
  • If you need just one side of test (if $var is empty and not need to execute the else) you can just use: [ expression ] && what you need to do. In this case you can just run: `[ -z "$var" ] && echo "empty"` – Mohamed Ali Benmansour Dec 03 '17 at 19:19
  • **BUG**: `[[: not found` on terminal UBUNTU – Peter Krauss Jun 09 '20 at 21:59
  • Suggestion: replace `# $var is empty, do what you want` with `echo "$var is empty, do what you want"`, so the snippet is copy-pastable. Otherwise it will throw an error at `fi` – DarkTrick Dec 28 '22 at 05:07
  • If there's so much discussion on the correctness of this answer, it should not be the accepted answer? Or the question should be narrowed down, so the answer holds? – DarkTrick Dec 28 '22 at 05:09
156

Presuming Bash:

var=""
if [ -n "$var" ]; then
    echo "not empty"
else
    echo "empty"
fi
alper
  • 2,919
  • 9
  • 53
  • 102
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 18
    The more direct answer is `-z`: `[[ -z "$an_unset_or_empty_var" ]] && echo empty` – glenn jackman Jun 17 '10 at 12:02
  • 4
    @glenn jackman: good comment; it's true that `-z` is closer to what was asked. Jay has put this in his answer so I'll refrain from updating mine and leave this up as is. – ChristopheD Jun 17 '10 at 19:10
  • 8
    Note that `-z` means Zero-length string, and `-n` means Non-zero-length string. Reference: https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html – Abel Wenning Feb 06 '22 at 04:43
56

I have also seen

if [ "x$variable" = "x" ]; then ...

which is obviously very robust and shell independent.

Also, there is a difference between "empty" and "unset". See How to tell if a string is not defined in a Bash shell script.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel Andersson
  • 1,614
  • 1
  • 14
  • 23
  • 1
    Looks strange to me. Could you please explain this solution. Thank you. – guettli Nov 12 '15 at 09:57
  • 2
    @guettli: If `$variable` is empty, then the string to the left of the comparison operator becomes only `x`, which is then equal to the string to the right of the operator. `[ x = x ]` is "true", so in practice this tests whether `$variable` is empty or not. As an addition (3½ years after the fact :-) ) I would never use this myself since `-z` does what I probably want in a clearer way, but I wanted to add this answer since this method is frequently seen "in the wild"; perhaps written this way on purpose by people who have had different experiences than I have. – Daniel Andersson Nov 12 '15 at 15:18
  • 1
    "Since this method is frequently seen "in the wild";" This is commonly seen in `configure` scripts, and it works with `sh` and any non-standard `bash` which might not have the `-z` flag. This situation was commonly the case when there were many flavors of Unix which were all mildly incompatible with each other in minor details, such as support for a `-z` flag. Now that Linux has taken over, it is not much of an issue (unless you are on an old, funny Unix) – Linas Mar 10 '21 at 15:36
38
if [ ${foo:+1} ]
then
    echo "yes"
fi

prints yes if the variable is set. ${foo:+1} will return 1 when the variable is set, otherwise it will return empty string.

matthias krull
  • 4,389
  • 3
  • 34
  • 54
alexli
  • 381
  • 3
  • 3
  • 5
    While not mentioned in the question, an important advantage of this answer is that it works even when the variable is undefined and the `set -u` option (`nounset`) is activated. Almost all other answers to this question will fail with `unbound variable` in this case. – anol May 26 '15 at 16:29
  • This `:+` notation is also useful for situations where you have optional command line parameters that you have specified with optional variables. `myprogram ${INFILE:+--in=$INFILE} ${OUTFILE:+--out=$OUTFILE}` – Alan Porter Jul 24 '18 at 19:59
12
[ "$variable" ] || echo empty
: ${variable="value_to_set_if_unset"}
pixelbeat
  • 30,615
  • 9
  • 51
  • 60
  • Great way to default out a var, plus 1 – ehime Dec 10 '13 at 17:16
  • 1
    @ehime to make a default value you would use `${variable:-default_value}` – warvariuc Nov 17 '15 at 09:25
  • This is a quick way to check the validity of an entry of a variable and exit if not set: `[ "$variable" ] || exit` – Marcel Sonderegger Jan 09 '19 at 12:40
  • Your first line is a re-implementation of the bash `track=${1:?"A Track number, like 't41', must be the first parameter"}`. Your second line does not work in bash; maybe you meant `: ${variable:="value_to_set_if_unset"}`. See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html – Cliff Jul 13 '23 at 15:22
11

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 I was actually searching for 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Luca Borrione
  • 16,324
  • 8
  • 52
  • 66
11
if [[ "$variable" == "" ]] ...
Amardeep AC9MF
  • 18,464
  • 5
  • 40
  • 50
9

This will return true if a variable is unset or set to the empty string ("").

if [ -z "$MyVar" ]
then
   echo "The variable MyVar has nothing in it."
elif ! [ -z "$MyVar" ]
then
   echo "The variable MyVar has something in it."
fi
3kstc
  • 1,871
  • 3
  • 29
  • 53
  • 5
    Why would you use `elif !` instead of `else`? – ZiggyTheHamster Nov 18 '15 at 01:55
  • 1
    Just to make a distinction between the two statements, ie using `! [ -z "$MyVar" ]` would mean that the variable would _have_ something in it. But ideally one would use `else`. – 3kstc Jun 19 '17 at 23:14
4

You may want to distinguish between unset variables and variables that are set and empty:

is_empty() {
    local var_name="$1"
    local var_value="${!var_name}"
    if [[ -v "$var_name" ]]; then
       if [[ -n "$var_value" ]]; then
         echo "set and non-empty"
       else
         echo "set and empty"
       fi
    else
       echo "unset"
    fi
}

str="foo"
empty=""
is_empty str
is_empty empty
is_empty none

Result:

set and non-empty
set and empty
unset

BTW, I recommend using set -u which will cause an error when reading unset variables, this can save you from disasters such as

rm -rf $dir

You can read about this and other best practices for a "strict mode" here.

dimid
  • 7,285
  • 1
  • 46
  • 85
1

To check if variable v is not set

if [ "$v" == "" ]; then
   echo "v not set"
fi
smishra
  • 3,122
  • 29
  • 31