Single square brackets [
and test
command both are built in the bash shell.
Why are there two separate commands if both square brackets [
and test
commands have the same function?
Single square brackets [
and test
command 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 ‘]’