Solved [Solved] test(1) possible bug

meadow

New Member


Messages: 11

Hello,

when writing a shell script I experienced behaviour of test(1), which I really cannot explain.

-z is supposed to be True if the length of string is zero.
-n is supposed to be True if the length of string is nonzero.

Here is a script that shows the behaviour:
Code:
#!/bin/sh

foo=

if [ -z $foo ] ; then
        echo "A"
fi

if [ -n $foo ] ; then
        echo "B"
fi
The output is to my surprise:
Code:
A
B
Did I miss something or is this a bug?
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,764
Messages: 30,893

Re: test(1) possible bug

Enclose the variable in double quotes:
Code:
#!/bin/sh

foo=

if [ -z "$foo" ] ; then
        echo "A"
fi

if [ -n "$foo" ] ; then
        echo "B"
fi
 
OP
OP
M

meadow

New Member


Messages: 11

Re: test(1) possible bug

Thanks! So the behaviour of test(1) is caused by some character that is added or already there (due to the nature of the shell) while evaluating, am I right?
 

kpa

Beastie's Twin

Reaction score: 1,809
Messages: 6,318

Re: test(1) possible bug

Well, @SirDice was quicker than me to respond :p The explanation why it behaves like that is a tricky one but you have to look at the strings passed to test(1) in both cases. Without the double quotes you are passing no argument to test -n because the shell does the expansion before building the argument list for test(1) and without the quotes there's not even an empty string left. With double quotes the value of "$foo" is properly an empty string that is passed as the first argument to test -n.

Edit: Sorry I'm writing rubbish again. Without double quotes what gets fed to test(1) is -n ] and the ] character is definitely a non-empty string.
 
Last edited by a moderator:

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,764
Messages: 30,893

Re: test(1) possible bug

It's hard to say, I would actually expect a syntax error as the line would be evaluated as
Code:
if [ -z  ] ; then
But it seems happy to accept it:
Code:
dice@armitage:~ % sh -x test.sh
+ foo=''
+ [ -z ]
+ echo A
A
+ [ -n ]
+ echo B
B
In any case, it's usually best to enclose variables in double quotes as the value could also contain spaces. And those are surely going to cause syntax errors:
Code:
dice@armitage:~ % sh -x test.sh
+ foo='it has spaces'
+ [ -z it has spaces ]
[: it: unexpected operator
+ [ -n it has spaces ]
[: it: unexpected operator
 
OP
OP
M

meadow

New Member


Messages: 11

Re: test(1) possible bug

Thanks. This is a bit tricky, but more or less clear. A syntax error would be definitely more robust.
 

kpa

Beastie's Twin

Reaction score: 1,809
Messages: 6,318

Re: test(1) possible bug

Another reason for the observed behaviour is that test(1) seems to treat the ] character as just another string and does not throw an error if it's the only argument to a test, like this: [ -n ]. It's 100% equal to writing test -n ].

All more reasons to drop the [] syntax (which isn't shell syntax at all really) for tests because it's so ambiguous. Better just write if test -n "$foo"; then ....
 
Top