[ -n ]
does not use the -n
test.
The -n
in [ -n ]
is not a test at all. When there is only one argument between [
and ]
, that argument is a string that is tested to see if it is empty. Even when that string has a leading -
, it is still interpreted as an operand, not a test. Since the string -n
is not empty--it contains two characters, -
and n
, not zero characters--[ -n ]
evaluates to true.
As Ignacio Vazquez-Abrams says, where string
is a single argument, the test performed on string
in [ string ]
is the same as the test performed on it by [ -n string ]
. When string
happens to be -n
, nothing special happens. The -n
in [ -n ]
and the second -n
in [ -n -n ]
are simply strings being tested for emptiness.
When there is only one argument between [
and ]
, that argument is always a string to be tested for nonemptiness, even if it happens to be named the same as a test. Similarly, when there are two arguments between [
and ]
and the first of them is -n
, the second one is always a string to be tested for nonemptiness, even if it happens to be named the same as a test. This is simply because the syntax for [
insists that a single argument between [
and ]
or after -n
is a string operand.
For the same reason that [ -n ]
doesn't use the -n
test, [ -z ]
doesn't use the -z
test.
You can learn more about [
in bash
by examining the help for it. Notice that is a shell builtin:
$ type [
[ is a shell builtin
Thus you can run help [
to get help on it:
$ help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
For more information, including what tests are supported and how they work, you will have to see the help on test
. When you run the command help test
, you'll get a detailed list. Rather than reproduce it all, here's the part about string operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Notice that -n STRING
and just STRING
do the same thing: they test if the string STRING
is not empty.
IFS
whitespace, will do that; variables that contain multiple words instead of zero produce another effect and may cause a completely different test to be run. Strings that appear literally with the intent of being operands will only work properly if they contain no spaces or tabs or if they are quoted. The answer would become much longer and more complicated if I covered this topic in an accessible way. If you decide to post answer, feel free to @ me here about it! – Eliah Kagan Oct 27 '17 at 16:01[ "$var" ]
would never be usable as a test because$var
might expand to-n
. – R.. GitHub STOP HELPING ICE Oct 28 '17 at 21:16test -n
. Cheers! – Sep 07 '18 at 21:52[ "$x" ]
and[ -n "$x" ]
? In my case they seem to behave identically; forx=""
both return 1, and forx="x"
both return 0. – pmor Jan 03 '24 at 12:38