11

The test [[ -n $1 ]] yields True if the length of string is non-zero.

But I've seen elsewhere and have tried using just [[ $1 ]] without the primary -n and it seems to have the same effect.

Is there any difference?

2
  • 6
    Note that with the standard [ ... ] (single brackets), there is a difference between [ -n $x ] and [ $x ] -- the first doesn't actually even work. That's because the unquoted expansion makes the whole word $x disappear if the variable is unset or empty, and the resulting commands are effectively [ -n ] and [ ]. The first of those is truthy, the second falsy. Though the unquoted expansion brings other issues too, [[ ... ]] avoids them by being special syntax that doesn't apply word splitting within it. Commented Nov 10 at 11:32
  • 4
    In addition to the excellent point raised by @ilkkachu, I would argue that even if [[ -n $x ]] and [[ $x ]] are semantically equivalent per the language spec, the first form is still preferred because it makes the intent more explicit. Commented Nov 10 at 12:18

1 Answer 1

15

There's no difference. In man bash, both the possibilities are shown as identical under CONDITIONAL EXPRESSIONS:

string
-n string
True if the length of string is non-zero.

At the prompt of the bash shell, you can also run help [[ to get the specific documentation for its [[...]] construct which lists the operators that it supports on top of or differently from the ones listed under help test.

In this instance, standard test/[ and Korn-style [[...]] work similarly, but [[ ... ]] allows you to leave expansions unquoted as no split+glob happens within. You'd need test -n "$1" / [ -n "$1" ] or test "$1" / [ "$1" ] with test/[.

Inside [[...]], you may however need to quote literal operands to avoid them being taken as operators, which points at one anecdotal difference between [[ -n string ]] and [[ string ]]: [[ -n -d ]] for instance returns true as -d is the non-empty string, but [[ -d ]] causes an error as -d in that position is taken as the -d operator. You'd need [[ "-d" ]] to test whether -d is the non-empty string without using -n. YMMV with other strings such as < which when not quoted causes an error with or without -n.

In contrast, test -f and test -n -f both return true as test relies on the number of arguments to decide which are operators and which are operands. In the one argument case, that argument is always treated as an operand for the implicit "is a non-null string" whether it also happens to be a test operator or not.

9
  • The command man bash shows a lengthy text. It's easier to use help test, at least on my computer. Commented Nov 10 at 16:46
  • @Wastrel: True, updates. I kept the original reference, though, as it corresponds to the link. Commented Nov 10 at 17:22
  • With mandoc: man -O tag=test bash. With man-db, one can type /^ +test after man bash and then press n a couple of times until the subtopic for test(1) is shown. Commented Nov 10 at 17:39
  • Of course, many systems just have a standalone manpage for test(1), so: man 1 test. Commented Nov 10 at 17:44
  • 3
    @PeterCordes, you have to quote variables inside [[ ... ]] in bash or ksh (or zsh when in sh or ksh emulation) when they are on the right hand side of the = (aka ==), != or =~ operators if you don't want their contents to be taken as a pattern as in [[ $a = "$b" ]] or [[ "$a" = "$b" ]] (or [[ $a =~ ^"$b"$ ]]) to check whether $a and $b expand to the same string (not guaranteed to work for the regexp variant). Commented Nov 10 at 20:00

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.