1

A recent test I took had a question on the output of the following bash command:

var=; [ -n $var ]; echo $?; [ -z $var ]; echo $?

The results are 0 and 0, indicating the return codes for both unary operators had no errors. This means $var resolves to both null (empty) and 'non-null' (not empty), correct?

How is this possible?

2
  • Those are unary operators. Commented Feb 16, 2013 at 4:12
  • info coreutils test invocation 16.3.4 String tests Commented Feb 16, 2013 at 7:39

3 Answers 3

3

No, it means that [ is unfixably broken. In both cases $var evaluates to nothing, and the commands simply execute [ -n ] and [ -z ] respectively, both of which result in true. If you want to test the value in the variable itself then you must quote it to have it handled properly.

$ var=; [ -n "$var" ]; echo $?; [ -z "$var" ]; echo $?
1
0
Sign up to request clarification or add additional context in comments.

1 Comment

It is not unfixably broken; it just has non-intuitive behavior. [ -n ] correctly reports that the string -n is not null, and [ -z ] correctly reports that the string -z is not null.
2

You will need to surround $var:

$ [ -n "$var" ]; echo $?
1

Remember that the closing square bracket is just syntactic sugar: you don't need it. That means your line:

$ [ -n $var ]; echo $?

will expand to (since $var is empty):

$ [ -n  ]; echo $?

The above asks: "is the string ']' non-empty?" And the answer is yes.

1 Comment

While [ is not syntax and in fact a synonym for the test command, you do need to use the closing ] with [.
1

It's surprising indeed. If you were to try the same with the bashism [[ syntax, you'd get 1 and 0 as results. I reckon this is a bug.

var=; [[ -n $var ]]; echo $?; [[ -z $var ]]; echo $?

or, as Ignacio points out and as in fact I have always been doing intuitively, with defensive coding and quoting:

var=; [[ -n "$var" ]]; echo $?; [[ -z "$var" ]]; echo $?

It's surprising to me that [ behaves this way, because it's a builtin:

$ type [
[ is a shell builtin

Just did a little test and the system command [ behaves in the same broken way as the builtin. So probably it's buggy for compatibility:

var=; /usr/bin/\[ -n $var ]; echo $?; /usr/bin/\[ -z $var ]; echo $?

2 Comments

[ has a lot of legacy behavior which cannot be modified, due to scripts depending on the broken-by-default behavior. Kind of like the Windows API.
@Ignacio Vazquez-Abrams: just noticed. Interesting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.