6

The zsh man page, in its section on test (aka [), explicitly advises against using it at all, and urges readers to use [[ whenever possible.

The relevant section states:

The command attempts to implement POSIX and its extensions where these are specified. Unfortunately there are intrinsic ambiguities in the syntax; in particular there is no distinction between test operators and strings that resemble them. The standard attempts to resolve these for small numbers of arguments (up to four); for five or more arguments compatibility cannot be relied on. Users are urged wherever possible to use the '[[' test syntax which does not have these ambiguities.

I think I've come across similar advice for bash, but as I scan over the bash man page I can't find any "official" recommendation there on which form ([ or [[) to use. (Maybe I missed it?)

Is there any reason, other than backward compatibility with "older shells", for using [ in a bash script? Or to put it differently, does bash keep [ along with [[ for reasons other than backward compatibility?

Michael Hampton
  • 8,658
  • 2
  • 31
  • 54
kjo
  • 14,779
  • 25
  • 69
  • 109
  • See also: [What is the difference between [[ $a == z* \]\] and [ $a == z* \]?](http://unix.stackexchange.com/a/56674/22565) – Stéphane Chazelas Mar 07 '13 at 12:40
  • Dang, usually the stackexchange interface saves me from posting duplicates, but this time it didn't: it showed exactly 0 suggestions for similar questions, which is pretty unusual, and maybe for this reason made me a bit over-confident... Sorry about that. – kjo Mar 07 '13 at 13:55

2 Answers2

5

There are some subtle differences though:

#!/bin/bash

eg=whatever

if [ $eg == what* ]; then   # file glob test
    echo '[]'
fi

if [[ $eg == what* ]]; then   # pattern match test
    echo "[[]]"
fi      

Unless there is a file called "whatever" in the current directory, the first test will not pass, because the match is against a file glob of the current directory contents, whereas the second one is an actual string pattern match.

goldilocks
  • 86,451
  • 30
  • 200
  • 258
4

The reason to prefer [ over [[ if sufficient is that [ is more stable between the different bash versions.

See man bash:

compat31

If set, bash changes its behavior to that of version 3.1 with respect to quoted arguments to the [[ conditional command's =~ operator.

compat32

If set, bash changes its behavior to that of version 3.2 with respect to locale-specific string comparison when using the [[ conditional command's < and > operators. Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); bash-4.1 and later use the current locale's collation sequence and strcoll(3).

compat40

If set, bash changes its behavior to that of version 4.0 with respect to locale-specific string comparison when using the [[ conditional command's < and > operators (see previous item) and the effect of interrupting a command list.

Maybe it is also a little bit more common to users with ksh background.

Note about performance

'[[' is quicker as '['

  • For a singular invocation the speed difference has no commensurable impact, and your should prefer the '[' builtin.
  • If you it inside a bigger loop construct, you may think of replace '[' with '[['

For a measurement you may use the following compare script

let upperBound=$1
echo "check [,  ${upperBound} iterations"
let i=0
time while [ $i -lt ${upperBound} ] ; do let i++ ; done

echo; echo;
echo "check [[, ${upperBound} iterations"
let i=0
time while [[ $i < ${upperBound} ]] ; do let i++ ; done

Result of compare script

check [, 1000 iterations

real 0m0.031s
user 0m0.028s
sys 0m0.004s

check [[, 1000 iterations

real 0m0.000s
user 0m0.000s
sys 0m0.000s

H.-Dirk Schmitt
  • 1,999
  • 11
  • 13
  • 1
    += And the reason to not use it — it's slower then (again) built-in version `[[`. – poige Mar 07 '13 at 12:07
  • I am not sure it makes much sense to select between `[` and `[[` based on _execution speed_, considering that Bash is an interpreted language that shouldn't really be used for performance-critical applications anyway. YMMV of course, but consider the wisdom of "Preliminary optimization is the root of all evil" (D. Knuth.) – András Aszódi Nov 30 '22 at 14:12