You always need quotes around variables in all list contexts, that is everywhere the variable may be expanded to multiple values unless you do want the 3 side effects of leaving a variable unquoted.
list contexts include arguments to simple commands like [
or echo
, the for i in <here>
, assignments to arrays... There are other contexts where variables also need to be quoted. Best is to always quote variables unless you've got a very good reason not to.
Think of the absence of quotes (in list contexts) as the split+glob operator.
As if echo $test
was echo glob(split("$test"))
.
The shell behaviour is confusing to most people because in most other languages, you put quotes around fixed strings, like puts("foo")
, and not around variables (like puts(var)
) while in shell it's the other way round: everything is string in shell, so putting quotes around everything would be cumbersome, you echo test
, you don't need to "echo" "test"
. In shell, quotes are used for something else: prevent some special meaning of some characters and/or affect the behaviour of some expansions.
In [ -n $test ]
or echo $test
, the shell will split $test
(on blanks by default), and then perform filename generation (expand all the *
, '?'... patterns to the list of matching files), and then pass that list of arguments to the [
or echo
commands.
Again, think of it as "[" "-n" glob(split("$test")) "]"
. If $test
is empty or contains only blanks (spc, tab, nl), then the split+glob operator will return an empty list, so the [ -n $test ]
will be "[" "-n" "]"
, which is a test to check wheter "-n" is the empty string or not. But imagine what would have happened if $test
was "*" or "= foo"...
In [ -n "$test" ]
, [
is passed the four arguments "["
, "-n"
, ""
and "]"
(without the quotes), which is what we want.
Whether it's echo
or [
makes no difference, it's just that echo
outputs the same thing whether it's passed an empty argument or no argument at all.
See also this answer to a similar question for more details on the [
command and the [[...]]
construct.
echo
, extra spaces and newlines would be stripped. – jordanm Feb 21 '13 at 16:28