Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portable way to check emptyness of a shell variable [duplicate]

What is the portable and canonical way to test if variable is empty/undefined in a shell script? It should work in all sh-like shells. What I do now is something like:

if [ -z "$var" ] ; then
    ...

and for reverse, doing something when variable is not empty/undefined:

if [ -n "$var" ] ; then
    ...

And while these work for the scripts I write now, I'd like to know a way, that will work in any reasonably compatible sh-like shell, even on some more obscure environment than a Linux PC with GNU userland and bash or dash.

I'm looking for an "expert answer" from someone who is experienced in different shell environments and knows the pitfalls of different ways of doing things, not an opinion like "that should work".

like image 616
hyde Avatar asked Nov 05 '13 07:11

hyde


1 Answers

The bracket construction [...] is part of the POSIX standard, and safe to just about everywhere. So, to test if a variable is empty the if case used in the question is perfect:

if [ -z "$STRING" ]; then
    # $STRING is empty
fi

As long as you remember than:

Always quote the variables

A non-quoted variable is subject to word splitting, so that if you use [ -z $STRING ] (without quotes around $STRING) and $STRING contains spaces, or is empty, the shell will see [ -z SEVERAL WORDS ] or [ -z ] which are both syntax errors – i.e. not what you want.

Always use just one equal sign

An alternative way if testing if a string in a POSIX shell is empty is to use =.

if [ "$STRING" = "" ]; then
    # $STRING is empty
fi

Note however that you should never use double equal signs (==) inside [...]! (This only works is bash, or when sh is a link to bash – but if run on a different machine where sh links to something else, it will not work.) If you want to use the double equal sign, you should also have double brackets [[...]] (which only works in zsh, bash etc., but not plain POSIX shells like dash).

Don't use && or || inside [...]

It might work in some shells, but it sure won't work in all of them. Instead, for 'and' write [...] && [...] or [... -a ...]. And for 'or' write [...] || [...] or [... -o ...].

Ancient stuff

Sometimes, in really ancient shell scripts you'll see stuff like the following, to test for an empty variable. This is still perfectly valid (but looks kind of clunky in my eyes) and I've never encountered a shell that requires this (though, admittedly, my experience is limited outside Linux – maybe there are BSD shells that still need this?)

if [ ".$STRING" = "." ]; then
    # $STRING is empty
fi

The prepending of a period is to avoid the bracket construction [...] from being confused if $STRING happen to contain -e, -o and other options that [...] uses. By prepending a period, it is turned into a non-option.

I have never seen a shell need this workaround, though. (Dash does certainly not need them.) So it is presumably safe to ignore this.

like image 120
zrajm Avatar answered Sep 23 '22 02:09

zrajm