[
command returns exit-status zero if expression, contained in its arguments, is considered true and non-zero exit-status if expression, contained in its arguments, is considered false. It also fails with error message if its last argument isn't ]
(this is done purely for aesthetic reasons).
E.g.:
[ hello ]
echo "Exit-status of [ hello ] is:" $?
[ abc = abc ]
echo "Exit-status of [ abc = abc ] is:" $?
[ ]
echo "Exit-status of [ ] is:" $?
[ abc = def ]
echo "Exit-status of [ abc = def ] is:" $?
… will output:
Exit-status of [ hello ] is: 0 — because non-empty string is considered true
Exit-status of [ abc = abc ] is: 0 — because 'abc' really is same as 'abc'
Exit-status of [ ] is: 1 — because empty string is considered false
Exit-status of [ abc = def ] is: 1 — because 'abc' really differs from 'def'
However, bash and many other shells really usually don't invoke /bin/[
(or /usr/bin/[
) in these cases, but call built-in command with exactly the same behavior instead (purely for performance reasons). To invoke /bin/[
(not shell built-in surrogate) you need either to explicitly specify its path (e.g. /bin/[ hello ]
; you don't need to prefix ]
with dirname though ☺), or to configure shell not to use a built-in surrogate (for example, enable -n [
in bash).
P. S.: As it was said in other answers, [
is related to test
. But test
, unlike [
, doesn't require ]
as its last argument (and doesn't expect it at all; adding extra ]
to test
arguments can cause it to fail with error message or to return wrong result). The /bin/test
and /bin/[
can resolve to the same file (e.g. one is symlinked; in this case the behavior diversion is probably implemented by analyzing the currently-called command within the test
/[
code itself) or to different files. For test
, shell also usually invokes built-in surrogate, unless path is explicitly specified (/bin/test
) or it's configured not to do so (enable -n test
).
P. P. S.: Unlike test
and [
, modern if
is never a real file. It's part of shell (e.g. bash) syntax: if commandA; then commandB; fi
(newlines can be used instead of semicolons) causes commandB
to be executed if-and-only-if commandA
exited with zero status. This perfectly fits to behavior of test
or [
, allowing to combine them like if [ "$a" = foo ]; then …; fi
(or if test "$a" = foo; then …; fi
— just less readable). However, modern scripts often use [[
instead of test
or [
, which (as the if
) is never a real file, but always a part of shell syntax.
P. P. P. S.: As for man
— never expect man
to have an article on every command in your file-system. Info on some (even "real", file-based) commands may be missing, info on some shell built-ins maybe present not only within an article dedicated to specific shell (that's the place where you most certainly will find info on test
, [
, if
, [[
). Still, many distributions have explicit man
-articles for test
and [
. (About --help
, it's not recognized with test
for obvious reason: it needs to handle quietly cases like a=--help; test "$a"
; on some distributions [ --help
(without closing ]
) still shows help, on some it doesn't.)
man expr
. – Ipor Sircer Jan 11 '17 at 08:02[
refers totest
command though, notexpr
, so it should beman test
– Sergiy Kolodyazhnyy Jan 11 '17 at 09:55man '['
works fine for me - either you forgot to quote[
or you have a different definition of "works". – Toby Speight Jan 11 '17 at 10:48[
has OS-specific implementations , which may or may not have a man page – Sergiy Kolodyazhnyy Jan 11 '17 at 11:01[
evaluates its arguments, so you need to have spaces between all of them.[ a=b ]
is not a comparison: it will always be true (it is a single string: "a=b", which is always evaluated to true) And you should limit the number of arguments to 4 (even though recent implementations will allow more... limiting to 4 makes it more portable. For example :[ "a" = "b" ]
already has 4 arguments : "a" "=" "b" and the non-necessary end of test arg : "]" ). If you need more: chain tests with for example:if [ "$Var_a" = "foo" ] && [ "$Var_b" = "bar" ] ; then : do something ; fi
– Olivier Dulac Jan 11 '17 at 12:02[
(the builtin version if your shell has one, or the one in/bin/[
) : ensure your shell really passes what you want it to pass. For that, you may need to escape some arguments. For example to negate, use'!'
or\!
if you use bash, otherwise bash will try to replace!
by the last command in history... ex:if [ \! -f "$1" ]; then echo "we need an existing regular file as first argument" ; fi
is usually more portable thanif [ ! -f "$1" ]
which may fail in bash as it will try to replace!
. – Olivier Dulac Jan 11 '17 at 12:10!
by itself (unescaped and unquoted) won't be replaced, and even better would beif ! [ ...
. All of the bash expansions that use!
include at least on other character – muru Jan 11 '17 at 12:23[
-builtin inbash
(and possibly other shells as well), and that this may be used instead of/bin/[
. Also there is thetest
-command, which on many systems is a symbolic link to/bin/[
(or vice versa) - but on others is a separate command. – Baard Kopperud Jan 11 '17 at 23:20