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?


[ 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 ‘]’

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.