I am always surprised that in the folder /bin there is a [ program.
Is this what is called when we are doing something like: if [ something ]?
By calling the [ program explicitly in a shell it asks for a corresponding ], and when I provide the closing bracket it seems to do nothing no matter what I insert between the brackets.
Needless to say, the usual way about getting help about a program does not work, i.e. neither man [ nor [ --help works.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The [ command’s job is to evaluate test expressions. It returns with a 0 exit status (that means true) when the expression resolves to true and something else (which means false) otherwise.
It’s not that it does nothing, it’s just that its outcome is to be found in its exit status. In a shell, you can find out about the exit status of the last command in $? for Bourne-like shells or $status in most other shells (fish/rc/es/csh/tcsh…).
$ [ a = a ] $ echo "$?" 0 $ [ a = b ] $ echo "$?" 1
In other languages like perl, the exit status is returned for instance in the return value of system():
$ perl -le 'print system("[", "a", "=", "a", "]")'
0
Note that all modern Bourne-like shells (and fish) have a built-in [ command. The one in /bin would typically only be executed when you use another shell or when you do things like env [ foo = bar ] or find . -exec [ -f {} ] ; -print or that perl command above…
The [ command is also known by the test name. When called as test, it doesn’t require a closing ] argument.
While your system may not have a man page for [, it probably has one for test. But again, note that it would document the /bin/[ or /bin/test implementation. To know about the [ builtin in your shell, you should read the documentation for your shell instead.
For more information about the history of that utility and the difference with the [[...]] ksh test expression, you may want to have a look at this other Q&A here.
Method 2
I am always surprised that in the folder
/binthere is a[program.
You are right to be surprised. That’s one of the rare POSIX commands, with the null utility (:), that doesn’t respect the commands file allowed characters convention (portable filename character set).
Is is what is called when we are doing something like:
if [ something ]?
Precisely but it can be used without the if too.
By calling the
[program explicitly in a shell it asks for a corresponding], and when I provide the closing bracket it seems to do nothing no matter what I insert between the brackets.
It does nothing visible but it actually does the very same thing than when used with if, i.e. it sets the exit status to 0 (true) or anything else (false) depending on what you put inside the brackets. It is (for a reason) the same behavior as the test command; the only difference is that it looks for the ending ]. See man test for details.
Needless to say, the usual way about getting help about a program does not work, i.e. neither
man [nor[ --helpworks.
That depends on your Operating System. man [ definitely works for me on a couple of mainstream Gnu/Linux distributions but it doesn’t on Solaris.
[ --help might work or not depending on the implementation as it is breaking the syntax anyway, missing the ending ]. Moreover, the POSIX standard for the test / [ command explicitly rules out all options, including the -- option termination so both [ --help ] and test --help need to return true and be silent by design. Note that what you put inside the brackets or after [ and that look like options (e.g. -f file, -n string, and the likes) are not options but operands.
All modern Bourne style shell interpreters (like bash, ksh, dash and zsh to name a few) implement the test/[ utility internally as a builtin so when you use them, the right manual page to refer to might be the one of the shell, not the test one.
Before Unix System III (1981), the Bourne shell didn’t implemented the test utility as a builtin so only the external binary command implementation was available. There wasn’t either a [ command (internal or builtin) until Unix System III so for example under Unix Version 7 you had to type:
if test something ; then …
instead of:
if [ something ] ; then …
Method 3
[ is actually more commonly known as test command. Typical use of this command is simply to evaluate expressions and return their condition – true or false. It is often used in if-then-else-fi statements, although it can be used outside of if statements to conditionally run other commands via shell’s && or || operators, like so.
$ [ -e /etc/passwd ] && echo "File exists" File exists $ test -e /etc/passwd && echo "File exists" File exists
More specifically, evaluation is communicated to other commands via exit status. Some programs may choose to output exit status to signify different types of events – program completing successfully, an error of particular type occurring during execution, or syntax errors. In the case of the test command, there are 0 signifies true, and 1 signifies false. As Stephan pointed out, syntax errors produce exit status of 2.
Its location depends on your system, and it also explains why you didn’t see man page when you did man [. For instance, on FreeBSD it is under /bin. On Linux (or in my particular case, Ubuntu 16.04) it is in /usr/bin/. If you do man [ or man test on a Linux system, you will see same documentation open. It’s also important to note that your shell may have its own implementation of test.
It should also be noted that this command has issues, which Korn shell’s implementation (commonly known as “conditional expression” reference with double square brackets, [[ "$USER" = "root" ]] ) seeks to resolve. This feature also used by other shells such as bash and zsh.
Method 4
Neither
man [nor[ --helpworks
On some distros (e.g. Ubuntu), man [ follows a symlink to test(1). On others (e.g. Arch), this is not the case. (But the test man page does document usage of [ as well)
type -a [ shows you that there’s both a shell builtin and an executable.
$ type -a [ [ is a shell builtin [ is /usr/bin/[
bash-builtin [ --help just prints an error message. (But since it’s a builtin, you can use help [, or look at the bash man page / docs).
/usr/bin/[ --help prints full help output (for the GNU Coreutils version), which starts out with:
$ /usr/bin/[ --help
Usage: test EXPRESSION
or: test
or: [ EXPRESSION ]
or: [ ]
or: [ OPTION
Exit with the status determined by EXPRESSION.
--help display this help and exit
--version output version information and exit
and then describes the allowed syntax for EXPRESSION.
This is another way you could have found out that [ and test are equivalent.
BTW, if you are programming for bash (or writing one-liners interactively), I’d recommend [[ instead of [. It’s better in several ways, see links in Serg’s answer.
Method 5
[ 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.)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0