I noticed while answering another question that test and [ are different binaries, but the [ manpage pulls up test's. Besides the requirement for an ending ], is there any difference? If not, why are they separate binaries instead of being symlinked? (They are also bash builtins, and bash doesn't show a difference either.)

2 Answers 2


The source code explains the difference as being how it handles the --help option.

  /* Recognize --help or --version, but only when invoked in the
     "[" form, when the last argument is not "]".  Use direct
     parsing, rather than parse_long_options, to avoid accepting
     abbreviations.  POSIX allows "[ --help" and "[ --version" to
     have the usual GNU behavior, but it requires "test --help"
     and "test --version" to exit silently with status 0.  */


$ /usr/bin/test --help
$ /usr/bin/[ --help
Usage: test EXPRESSION
  or:  test
  or:  [ EXPRESSION ]
  or:  [ ]
  or:  [ OPTION
Exit with the status determined by EXPRESSION.

In the bash builtin version, the only difference is that [ requires ] at the end, as you said.

  • 1
    Interesting, though most programs achieve the same behavior with a symlink.
    – Kevin
    May 6, 2012 at 16:33
  • 2
    They're hardlinks to the same inode on my system. The benefit of this over symlinks is that if the symlink target gets removed or moved, the symlink no longer works. If one of the hardlinks to an inode gets moved or removed, all the hardlinks continue to work.
    – nobody
    Jun 20, 2014 at 15:56

Normally, they are the same binary with hard links. Depending on the shell, an internal implementation may be used for test and [ tests rather than the binary. This is more efficient in terms of process spawning, and may provide different options than the binary program test provides.

Other than the the differences in call format, they both provide the same functionality.

  • 8
    Amazingly enough, in Debian's coreutils they aren't the same binary. The same source is compiled two times, one defining PROGRAM_NAME as "test", and other defining it as "[" and with some additional code to test that the expression ends with "]". o_O
    – angus
    Jan 9, 2012 at 17:58
  • 3
    @angus Another example of this is ls/dir/vdir. Coreutils seems to like building different hardcoded binaries rather than testing argv[0] at runtime.
    – Random832
    Jan 9, 2012 at 18:22

You must log in to answer this question.

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