When do you use (( )) or /usr/bin/test

You use /usr/bin/test when you want things to run more slowly. Modern shells (most shells released since about 1990, probably earlier) have test and its synonym [ as built-in commands. Formally invoking /usr/bin/test would be an act of desparation because the shell has a broken test command and the system standalone is OK - but it would be better to get a fixed shell.

You use (( ... )) to do arithmetic. The old-fashioned alternative was the expr command. That was tricky to use because it required a lot of escaping - it is/was a separate executable, and you had to get lots of shell metacharacters past the shell to expr. Hence:

x=$(expr $y '*' $z)

instead of

((x = y * z))

You don't even have to decorate the variables with $ in (( ... )).


(( )) evaluates an arithmetic expression in bash (see man bash).
[[ ]] evaluates a logic expression in bash (see man bash).
[ ] is the same as test, used to check file types and compare values (see man test).


To answer your question:

  • you want to use /usr/bin/test when you want to test something but not in a shell (for example find ... -exec test ...)
  • you want to use (( )) when you have an arithmetic expression to solve, AND you are using bash, because (( )) is bash specific.

Now for some background:

The command /usr/bin/test is required by the POSIX standard. POSIX also requires that [ is defined as an alias for test. The only difference between test and [ is that [ requires the final parameter to be a ].

Since test is used so frequently in shell scripts, most shells have a builtin version of test (and [). The advantage of a builtin is that it avoids context switches. Which, depending how you use test in your script, can be a measurable performance advantage.

I think it is safe to assume that under most circumstances it doesn't matter whether you use the system test or the shell's builtin test. But if you want to use test in a find -exec situation then of course you have to use the system test because find cannot use the shell test.

(( )) and [[ ]] were introduced by bash (and perhaps some other shells) as syntactic sugar. (( )) evaluates arithmetic expressions, while [[ ]] evaluates logical expressions. Both allow you to write the expressions in a "more natural syntax".

The decision to use [[ or [ depends on whether you want to use the "more natural syntax", and, since sh does not support [[, whether you want to depend on bash.

The decision to use (( )) depends on whether you need arithmetic expressions, and again, since sh does not support (( )), whether you want to depend on bash. The POSIX alternative to (( )) is $(( )). Note that there are some subtle differences in the behaviour.

The following links explain these topics in great detail:

  • http://mywiki.wooledge.org/BashFAQ/031 (difference between test, [ and [[)
  • http://mywiki.wooledge.org/ArithmeticExpression (let, (( )) and $(( )))
  • http://www.ibm.com/developerworks/library/l-bash-test/index.html (all of the above)

See also:

  • POSIX definition of test
  • POSIX definition of $(( ))

Bonus: Some debian developers once argued whether they should use the system test or the shell builtin test, because of some differences in the implementation of the builtin test. If you are interested in details of the differences of the system test and the shell builtin test then you can read the debian developer discussion here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=267142.

Tags:

Unix

Shell