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

[ -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?


If set -u is in effect, and VAR is unset, [ -z "$VAR" ] will cause an error. With [ -z "${VAR-}" ] the default value overrides the check for using an unset variable, and there is no error.

  • Well, 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 4:23
  • BTW, use of set -u in conjunction with pervasive use of ${VAR:-} would be self-defeating to the extreme. – Greg A. Woods Jun 15 '17 at 4:27
  • @GregA.Woods, regardless of how usual it is, if it's enabled, there is a difference. I do rather find set -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 4:28
  • 1
    ${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 like set -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:51
  • 2
    I also find it a lot more robust to avoid relying on any distinction between empty and unset variables, especially in shell scripts. Binary logic is usually much easier to follow and prove correct than ternary logic. – Greg A. Woods Jun 15 '17 at 17:18

You are absolutely right -- there is no reason to use the form ${VAR:-} nor the form ${VAR-} with either test -n or test -z.

I've not seen this myself, so I can only guess that inexperienced shell programmers might think there's some difference between an unset value and an empty value with respect to how test -n works, but that could only happen if test (i.e. [) is both a built-in, and buggy; or if someone is trying to use set -u without thinking through the implications of then defending against it in this manner.

  • Is ${VAR-} really deprecated? It's behavior differs from the :- version if VAR is set to null. – ivan Jun 15 '17 at 4:10
  • 2
    ${VAR:-foo} and ${VAR-foo} are not the same, and there's no reason to think one is deprecated. (Okay, fine, with an empty default value, there's no difference.) – ilkkachu Jun 15 '17 at 4:11
  • Well, there's been no mention of ${VAR-} in POSIX since at least 1003.1-2004. It's not in the 10th Edition Research Unix manual either, and that came out in 1989. – Greg A. Woods Jun 15 '17 at 4:17
  • 2
    @GregA.Woods, IEEE Std 1003.1-2008, 2016 Edition, Shell Command Language/Parameter Expansion. There's a nice table of the eight similar forms. The manuals for some shells are a bit more vague on it, e.g. Bash's manual only mentions in the middle of the text what happens if the colon is omitted. – ilkkachu Jun 15 '17 at 4:37
  • Ah, my mistake -- my reference to the 2004 edition was incomplete. (I wish POSIX hadn't used the word "null" to refer to an empty shell variable. To most programmers with experience with pointers (or SQL for that matter) "null" means un-set, and "empty" is, well, empty.) – Greg A. Woods Jun 15 '17 at 5:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.