Bash: check if a variable is declared (with declare)

71 views Asked by At

How to check in Bash (5.x) if a variable is declared, after set for a failing command.

E.g.:

That should output No fail, because FAIL is not declared:

echo "Test" || declare -r FAIL
if [ -v FAIL ]; then echo "Fail"; else echo "No fail"; fi;

That should output Fail, because FAIL is declared:

some_command_not_existing || declare -r FAIL
if [ -v FAIL ]; then echo "Fail"; else echo "No fail"; fi;

However this is not working as expected. I also tried with -z but this is also not working.

I could just make FAIL=true, but I wanted to avoid an unnecessary string.

1

There are 1 answers

1
glenn jackman On

declare can tell you if a variable is declared.

First, looking at set and -v

$ FAIL=
$ [[ -v FAIL ]] && echo set || echo not set
set
$ unset FAIL
$ [[ -v FAIL ]] && echo set || echo not set
not set

This much we know.

Now, how about declared but unset variables?

$ declare -i FAIL
$ [[ -v FAIL ]] && echo set || echo not set
not set
$ declare -p FAIL && echo declared || echo not declared
declare -i FAIL
declared
$ unset FAIL
$ declare -p FAIL && echo declared || echo not declared
bash: declare: FAIL: not found
not declared

And, to remove the output from declare

$ unset FAIL
$ declare -p FAIL >/dev/null 2>&1 && echo declared || echo not declared
not declared
$ declare -i FAIL
$ declare -p FAIL >/dev/null 2>&1 && echo declared || echo not declared
declared

If you want a variable set with a non-empty variable to be OK, and any other case to be not OK, you can use -n

$ unset FAIL
$ [[ -n $FAIL ]] && echo ok || echo not ok
not ok
$ FAIL=
$ [[ -n $FAIL ]] && echo ok || echo not ok
not ok
$ FAIL=foo
$ [[ -n $FAIL ]] && echo ok || echo not ok
ok

Note the the double bracket conditional is more forgiving about unquoted variables. For single bracket conditional, quote it.

$ unset FAIL
$ [ -n $FAIL ] && echo ok || echo not ok    # oops, wrong result
ok
$ [ -n "$FAIL" ] && echo ok || echo not ok
not ok

Referencing an unset variable clashes with set -u. For this you can use parameter expansion.

$ unset FAIL
$ set -u
$ [[ -n $FAIL ]] && echo ok || echo not ok
bash: FAIL: unbound variable
$ [[ -n ${FAIL-""} ]] && echo ok || echo not ok
not ok