ksh question: what's the difference between [ ... ] and [[ ... ]] ?
Eduardo Krell
ekrell at ulysses.att.com
Fri Aug 10 23:54:12 AEST 1990
Answer from Dave Korn:
The primary difference between [ and [[ is that [ is a command
(equivalent to the test command), whereas [[ is part of the shell
grammar. There are a few minor differences as well. In particular,
[ uses -a and -o for and and or, whereas [[ uses && and || for this.
Because [ is a command, all shell expansions are performed before
the [ command is executed. The only way to distinguish between
operators and operands is by the results of expansions. For example,
[ "$1" ]
can have several meanings that depend of the value of $1. If $1
is -t, then this is a test for a terminal. If $1 is of the form,
-<letter>, where letter is one of the unary operators that require an
operand, then this is an error. Otherwise, this evaluates to true when
the string is not null. Note that the use of double quotes is critical
with [ since otherwise it need not expand to a single argument which
leads to unexpected results.
There are many other anomalies with [. Here are a few:
1. To test string variables you have to precede the
variable with a character that is not a - to prevent
it being interpreted as an operator.
2. [ -f * ] tests the first file name and ignores the
rest, unless the second name is -a, -o, or a binary
operator such as =.
3. [ -f "$1" ] yields a syntax error when $1 is =.
The [[...]] construct was added to ksh88 to overcome these problems.
Since [[...]] is part of the shell, it can differenciate between
operators and operands before expansion. (This means that the operators
cannot be variable unless you use eval). In addition, word splitting
and file name expansion are not performed inside [[...]] eliminating
many of the most common scripting errors. Because no file expansion is
done, pattern characters (*,? and [) can be used for string comparison.
The [[...]] construct was in draft 8 of the IEEE 1003.2 shell and
utilities standard, but was removed from draft 9 because it was felt
that some of these problems could be fixed by eliminating compound
operations, -a, -o, !, and () in test ([) from the standard and requiring
that -t require an operand. The number of arguments could then determine
which argument was an operator. Writing a compound command would
requiring the use the && and || of the shell instead. The ! command was
added to the shell grammar for this purpose. Unfortunately, there
was no coordination between changes in test and the shell language
so that the changes in test were never made and the [[...]] was not
restored. Therefore, unless there is a change in future version of
the standard, the [[...]] will remain a KornShell extension rather
than part of the POSIX shell language.
David Korn
ulysses!dgk
Eduardo Krell AT&T Bell Laboratories, Murray Hill, NJ
UUCP: {att,decvax,ucbvax}!ulysses!ekrell Internet: ekrell at ulysses.att.com
More information about the Comp.unix.questions
mailing list