What is the best way to determine if a variable in bash is empty ("")?
I have heard that it is recommended that I do if [ "x$variable" = "x" ]
Is that the correct way? (there must be something more straightforward)
What is the best way to determine if a variable in bash is empty ("")?
I have heard that it is recommended that I do if [ "x$variable" = "x" ]
Is that the correct way? (there must be something more straightforward)
This will return true if a variable is unset or set to the empty string ("").
if [ -z "${VAR}" ];
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 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} ]]
A variable in bash (and any POSIX-compatible shell) can be in one of three states:
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.
-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.
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
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.
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:
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.
the entire if-then and -z are unnecessary.
[ "$foo" ] && echo "foo is not empty" [ "$foo" ] || echo "foo is indeed empty"
Personally prefer more clear way to check :
if [ "${VARIABLE}" == "" ]; then
echo VARIABLE is empty
else
echo VARIABLE is not empty
fi
My 5 cents: there is also a shorter syntax than if ...
, this one:
VALUE="${1?"Usage: $0 value"}"
This line will set VALUE if an argument has been supplied and will print an error message prepended with the script line number in case of an error (and will terminate the script execution).
Another example can be found in the abs-guide (search for «Example 10-7»).
This is true exactly when $FOO is set and empty:
[ "${FOO+x}" = x ] && [ -z "$FOO" ]
oneliner extension of duffbeer703's solution:
#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
To figure out if a variable "Foo" is empty and also contains no spaces (or no whitespace as some people refer it).
if [[ -n "${Foo/[ ]*\n/}" ]];then
echo "Foo is not empty and contains non space characters"
fi
# Another way to solve the same problem: Take spaces out in Foo & check if Foo is empty
if [[ -z "${Foo// }" ]];then
echo "Foo is empty"
fi
I prefer the way how PHP checks for an empty variable as Luca mentioned in his answer, too. But instead of using a separate function, I use a "filter" which finally allows using usual bash conditions.
Imagine you have a bash script with a settings section like this:
# enable test mode
dry_run=false
# overwrite files if they already exist
overwrite_files=true
The users of the script should be able to set it as they like:
dry_run=
dry_run=""
dry_run=0
dry_run="0"
dry_run=false
dry_run="false"
# or delete it completely
So in the script section itself I do this:
# check user settings
[[ $dry_run == 0 ]] || [[ $dry_run == false ]] && unset dry_run
[[ $overwrite_files == 0 ]] || [[ $overwrite_files == false ]] && unset overwrite_files
Now, I can be sure that the variable exists with a content or not, so I can use a usual condition like this:
if [[ $dry_run ]]; then
echo "dry run is true"
else
echo "dry run is false"
fi
PS I skipped filtering "0.0" as I don't think a user would disable a setting by setting this, but feel free to extend the filter if you need it.
Not an exact answer, but ran into this trick. If the string you're looking for comes from "a command" then you can actually store the command in an env. variable and then execute it every time for the if statement, then no brackets required!
For example this command, which determines if you're on debian:
grep debian /proc/version
full example:
IS_DEBIAN="grep -i debian /proc/version"
if $IS_DEBIAN; then
echo 'yes debian'
else
echo 'non debian'
fi
So this is like an indirect way (rerunning it every time) to check for an empty string (it happens to be checking for error response from the command, but it also happens to be returning an empty string).