I understand test -n <expression>
to return false if the expression evaluates to a string length of greater than 0. Why then does the following happen?
Macbook:~ echo ${#undeclared_variable}
0
Macbook:~ test -n $undeclared_variable && echo Foo
Foo
Bash 4.x
My expectation is that since test -n $undeclared_variable
should evaluate false, that Foo should not be echoed. If I use [[ ]]
instead of test, it works as expected.
Best Answer
You need to quote your variables. Without quotes you are writing
test -n
instead oftest -n <expression>
. Thetest
command has no idea that you provided a variable that expanded to nothing.In the syntax of POSIX shells like
bash
,$VARIABLE
outside of double quotes is the “split+glob” operator: the value of the variable is split into a list of whitespace-delimited words, and each word is interpreted as a wildcard pattern and replaced by the names of matching files (or left alone if there is no matching file). If the value of the variable is empty, the list of words after splitting is an empty list. To obtain the value of the variable without further processing, the variable expansion needs to be inside double quotes.The reason
[[
works is because it's a bash special syntax and not a command; within this special syntax,$VARIABLE
means “value ofVARIABLE
” (except on the right-hand side of the pattern matching operators=
,==
,!=
and=~
). Using[
would function the same astest
. The following does what you want: