Jay Taylor's notes

back to listing index

Test if a variable is set in bash when using "set -o nounset"

[web search]
Original source (stackoverflow.com)
Tags: bash shell-scripting stackoverflow.com
Clipped on: 2016-05-05

The following code exits with a unbound variable error. How to fix this, while still using the set -o nounset option?

#!/bin/bash

set -o nounset

if [ ! -z ${WHATEVER} ];
 then echo "yo"
fi

echo "whatever"
asked Oct 20 '11 at 6:44
Image (Asset 3/8) alt=
vinodkone
6801918
up vote 28 down vote accepted
#!/bin/bash

set -o nounset


VALUE=${WHATEVER:-}

if [ ! -z ${VALUE} ];
 then echo "yo"
fi

echo "whatever"

In this case, VALUE ends up being an empty string if WHATEVER is not set. We're using the {parameter:-word} expansion, which you can look up in man bash under "Parameter Expansion".

answered Oct 20 '11 at 6:52
Image (Asset 5/8) alt=
Angelom
1,20977
1 upvote
  flag
awesome thanx! looks like -z ${WHATEVER:-} works too... – vinodkone Oct 20 '11 at 7:00
2 upvote
  flag
just replace if [ ! -z ${VALUE} ]; with if [ ! -z ${WHATEVER:-} ]; – Angelom Oct 20 '11 at 7:00
11 upvote
  flag
:- checks whether the variable is unset or empty. If you want to check only whether it's unset, use -: VALUE=${WHATEVER-}. Also, a more readable way to check whether a variable is empty: if [ "${WHATEVER+defined}" = defined ]; then echo defined; else echo undefined; fi – l0b0 Oct 24 '11 at 11:04
   upvote
  flag
Also, this won't work if $WHATEVER contains only whitespace - See my answer. – l0b0 Mar 22 '12 at 15:07

You need to quote the variables if you want to get the result you expect:

check() {
    if [ -n "${WHATEVER-}" ]
    then
        echo 'not empty'
    elif [ "${WHATEVER+defined}" = defined ]
    then
        echo 'empty but defined'
    else
        echo 'unset'
    fi
}

Test:

$ unset WHATEVER
$ check
unset
$ WHATEVER=
$ check
empty but defined
$ WHATEVER='   '
$ check
not empty
answered Mar 22 '12 at 15:03
Image (Asset 6/8) alt=
l0b0
17.7k560114
   upvote
  flag
I tried this and I'm surprised this works... Everything is correct except according to "info bash", "${WHATEVER-}" should have a ":" (colon) before the "-" (dash) like: "${WHATEVER:-}", and "${WHATEVER+defined}" should have a colon before the "+" (plus) like: "${WHATEVER:+defined}". For me, it works either way, with or without the colon. On some versions of 'nix it probably won't work without including the colon, so it should probably be added. – Kevin Fegan Jan 7 '14 at 20:58
1 upvote
  flag
Nope, -, +, :+, and :- are all supported. The former detect whether the variable is set, and the latter detect whether it is set or empty. From man bash: "Omitting the colon results in a test only for a parameter that is unset." – l0b0 Jan 7 '14 at 21:00
   upvote
  flag
Nevermind =). You are correct. I don't know how I missed that. – Kevin Fegan Jan 7 '14 at 21:11
   upvote
  flag
From the docs: Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence. – A-B-B Apr 3 '14 at 0:25
$ echo $SHELL
/bin/bash
$ /bin/bash --version | head -1
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
$ set -o nounset

If you want a non-interactive script to print an error and exit if a variable is null or not set:

$ [[ "${HOME:?}" ]]

$ [[ "${IAMUNBOUND:?}" ]]
bash: IAMUNBOUND: parameter null or not set

$ IAMNULL=""
$ [[ "${IAMNULL:?}" ]]
bash: IAMNULL: parameter null or not set

If you don't want the script to exit:

$ [[ "${HOME:-}" ]] || echo "Parameter null or not set."

$ [[ "${IAMUNBOUND:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.

$ IAMNULL=""
$ [[ "${IAMUNNULL:-}" ]] || echo "Parameter null or not set."
Parameter null or not set.

You can even use [ and ] instead of [[ and ]] above, but the latter is preferable in Bash.

Note what the colon does above. From the docs:

Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.

There is apparently no need for -n or -z.

In summary, I may typically just use [[ "${VAR:?}" ]]. Per the examples, this prints an error and exits if a variable is null or not set.

answered Apr 3 '14 at 16:41
Image (Asset 7/8) alt=
A-B-B
6,66923026

How about a oneliner?

[ -z "${VAR:-}" ] && echo "VAR is not set or is empty" || echo "VAR is set to $VAR"

-z checks both for empty or unset variable

answered Jun 29 '12 at 14:56
Image (Asset 8/8) alt=
NublaII
693
   upvote
  flag
No, -z only checks if the next parameter is empty. -z is is just an argument of the [ command. Variable expansion happens before [ -z can do anything. – dolmen Mar 30 '15 at 21:39

You can use

if [[ ${WHATEVER:+$WHATEVER} ]]; then

but

if [[ "${WHATEVER:+isset}" == "isset" ]]; then

might be more readable.

answered Mar 22 '12 at 14:49
   upvote
  flag
String comparisons should use the standard (POSIX) = operator, not == to aid in portability, and [ instead of [[ if possible. – Jens Oct 26 '12 at 9:30

Your Answer

asked

4 years ago

viewed

14419 times

active

9 months ago

Hot Network Questions

Technology Life / Arts Culture / Recreation Science Other
  1. Stack Overflow
  2. Server Fault
  3. Super User
  4. Web Applications
  5. Ask Ubuntu
  6. Webmasters
  7. Game Development
  8. TeX - LaTeX
  1. Programmers
  2. Unix & Linux
  3. Ask Different (Apple)
  4. WordPress Development
  5. Geographic Information Systems
  6. Electrical Engineering
  7. Android Enthusiasts
  8. Information Security
  1. Database Administrators
  2. Drupal Answers
  3. SharePoint
  4. User Experience
  5. Mathematica
  6. Salesforce
  7. ExpressionEngine® Answers
  8. more (13)
  1. Photography
  2. Science Fiction & Fantasy
  3. Graphic Design
  4. Movies & TV
  5. Seasoned Advice (cooking)
  6. Home Improvement
  7. Personal Finance & Money
  8. Academia
  9. more (9)
  1. English Language & Usage
  2. Skeptics
  3. Mi Yodeya (Judaism)
  4. Travel
  5. Christianity
  6. Arqade (gaming)
  7. Bicycles
  8. Role-playing Games
  9. more (21)
  1. Mathematics
  2. Cross Validated (stats)
  3. Theoretical Computer Science
  4. Physics
  5. MathOverflow
  6. Chemistry
  7. Biology
  8. more (5)
  1. Stack Apps
  2. Meta Stack Exchange
  3. Area 51
  4. Stack Overflow Careers
site design / logo © 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.5.5.3546