I see a lot of shell scripts (for example, this one) checking for a variable's presence/absence like:
[ -n "${VAR-}" ]
As far as I can tell, using the ${VAR-fallback}
form without providing a fallback
serves no purpose when checking for variable presence/absence (-n
or -z
). The same goes for ${VAR:-fallback}
. For example, with an unset variable,
unset VAR
[ -z "$VAR" ] &&
[ -z "${VAR-}" ] &&
[ -z "${VAR:-}" ] &&
echo True # => True
and with a null variable
VAR=
[ -z "$VAR" ] &&
[ -z "${VAR-}" ] &&
[ -z "${VAR:-}" ] &&
echo True # => True
But I see it in enough places that I have to ask, am I missing something? Is it just a misunderstanding that results in misuse, or is there actually a reason to do it?
set -u
is very unusual in practice, and normally would only be seen inside the script itself, which again would be highly unusual. It can be useful for debugging I suppose, but defending against it in normal scripting is pedantic, to say the least. – Greg A. Woods Jun 15 '17 at 04:23set -u
in conjunction with pervasive use of${VAR:-}
would be self-defeating to the extreme. – Greg A. Woods Jun 15 '17 at 04:27set -u
useful. Not as a way to crash on purpose, but as a way to hedge against mistyping variable names. Even if you used"${foo-}"
everywhere, it would have the advantage of explicitly making you think about the possibility of the variable being unset. – ilkkachu Jun 15 '17 at 04:28set -u
-- just against the insanity of defending against it blindly with${VAR:-}
. – Greg A. Woods Jun 15 '17 at 04:35set -eu
, which is easy to miss in the diff I linked. – ivan Jun 15 '17 at 12:32set -e
doesn't error out if a command substitution fails, so you don't need that|| :
within it. – ilkkachu Jun 15 '17 at 12:48${var-}
is useful when checking if a variable that comes from outside the script itself is set or empty (or${var+x}
to check if it's set). I've used stuff likeset -u; if [ -z "${1-}" ] ; then complain...
(Yes, you could use$#
for positional parameters, but not for some environment variable in general.) – ilkkachu Jun 15 '17 at 12:51set -e
and the command substitution, so I tried it out, and it did actually error out without the|| :
. Maybe it depends on the bash version? – ivan Jun 15 '17 at 16:13exit
command, and usually also preceded by an explicit and informative error message. Having the shell bomb out itself isn't very useable except in the most trivial cases such as one-off scripts, or script fragments used within makefiles, etc. That means doing tests for unset or empty variables in ways that don't cause the shell to die. – Greg A. Woods Jun 15 '17 at 17:17set -u
was to hedge against mistyping variable names. If you don't make mistakes, you won't need it. But if you use it, you have some situations where you may also need the default value expansions. – ilkkachu Jun 16 '17 at 08:16set -u
is more of a sledge hammer than a fine programming tool. For a one-off script it might be OK, but for anything big enough where misspellings are hard to find, it's going to be more trouble than it's worth, even in the test and debug phase. I'm more inclined to use the better tools for the job. Modern text editors are pretty good at finding mis-spelled variables, though with some it can be a bit more tedious than with others. – Greg A. Woods Jun 16 '17 at 19:59