10

Single square brackets [ and testcommand both are built in the bash shell.

Why are there two separate commands if both square brackets [ and test commands have the same function?

1

1 Answer 1

20

[ and test are the same command. Only, [ expects its last argument to be ] (which it otherwise ignores).

The [ and test command are often implemented by the same binary file. Most Bourne-like shells and fish have both [ and test builtin. The C shell or rc and their derivatives don't. The C shell has dedicated constructs to perform some of the operations normally performed by the test/[ utility.

The test command appeared in Unix V7 in the late 70s alongside the then new Bourne shell. Previous versions had no test command, and their shell didn't have a if construct. But there was a standalone if command that could do a few of the same tests that test does and execute a command depending on the result.

The Bourne shell introduced a few control statements (if/while/until), so test was introduced to complement that, to have a command which could be used in the condition part of those statements to perform various tests.

There was no [ command in V7, but you can find some unfinished commented out code in there for a [ builtin suggesting they had already envisioned it by then, but probably decided against cluttering the sh code with it at the time.

[ and test builtins were added to the Bourne shell in System III in 1981.

All Bourne-like shells including bash have had a [/test builtin since then, but note that while the Almquist shell had [/test built-in from the start (actually merged with expr), it was initially disabled (not compiled in) in early BSDs and until quite late in some.

Both [ and test are standard POSIX commands. They are not required to be builtin, but they are required to be executable from things like env, find -exec, execvp(), etc, so be available as standalone executable.

You still find some systems though that supply a standalone test utility but not a [ one. Which explains why you see more often things like:

find . -exec test -f {} ';'

(equivalent of GNU find's -xtype f), than:

find . -exec [ -f {} ] ';'

Which would fail on systems that don't supply a standalone [ utility.

As another anecdotal difference between [ and test, since test <any-string> (same as [ <any-string> ]) is a valid test which tests whether <any-string> is non-empty, test --version or test --help cannot return the version of test or its usage. [ --version however is not a valid test, so you'll find that the GNU standalone [ utility accepts --version and --help to return version and usage information respectively, instead of the usual missing ‘]’ error message while GNU test doesn't (see corresponding commit from 2003 (misleading comment fixed in 2005)).

$ '/usr/bin/[' --version
[ (GNU coreutils) 8.30
[...]
$ /usr/bin/test --version && echo "--version is non-empty"
--version is non-empty
$ '/usr/bin/[' --something-else
/usr/bin/[: missing ‘]’
1
  • 1
    thanks for referencing that commit from 1979!
    – charsi
    Commented Jan 1, 2023 at 7:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .