2

New to bash scripting. In the beginning of a bash script a variable is initialized

silent_install=true

Then this variable is used in the following 2 ways in the script

if [ -z "$silent_install" ]; then

and

if [ -z ${silent_install} ]; then

What is the difference between the 2 usages?

3 Answers 3

7

Short: the second one is wrong.

Wrong because an unquoted variable will be subject of word splitting. If the variable contains spaces the test will fail.

The {} does not make a difference, you can use them or not, with or without quotes. However, generally I would advice to use them. Especially if you interpolate them like "$foo_bar". What's the variable name here? "${foo}_bar" is much cleaner.

I would consequently use:

if [ -z "${silent_install}" ] ; then
2
  • 1
    @DevSolar You are right. (I didn't added that to my answer to keep it clear.) Since the extended test [[ ]] is a bash syntax feature rather than an external command (or command builtin), word splitting would not happen in that case.
    – hek2mgl
    Commented Feb 27, 2016 at 15:44
  • 2
    @DevSolar Actually, there are some cases where double-quotes matter even in [[ ]], such as on the right-hand side of a string comparison. IMO double-quoting everywhere is easier than trying to keep track of where it matters & where they're safe to leave off. Commented Feb 27, 2016 at 16:07
2

You should use the double quotes making it ONE string. With the value true you will see no difference, but you will get into trouble when silent_install has special characters or spaces (silent_install="I do not know").
Start getting used to {}. They do not matter here, but will matter when you have oher characters right after it ($SILENT_INSTALLandmore).
UPPERCASE characters are reserved for bash, so use if [ -z "${silent_install}" ]

2

In addition to the problems with word splitting the other answers point out, there's another problem with [ -z ${silent_install} ]. In one of the expected cases, where silent_install is unset or blank, the test command expands to [ -z ]. When the [ command gets an expression with just a single argument, it tests that argument to see if it's non-blank. In this case, "-z" is non-blank, so the test returns true. This is the expected result, but that's just a coincidence; it's actually testing something very different from what the script author assumed it was.

The more serious variant of this scripting problem is the reverse test, [ -n ${somevar} ] (-n means "is not blank", the opposite of -z). Because [ -n ] actually tests whether -n is non-blank, it returns true, which is the opposite of what you'd expect.

The moral of the story is "double-quote your variable references!" It prevents all sorts of weird bugs and unexpected behavior.

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