I see there is an executable called "[" in /usr/bin
. What is its purpose?
3 Answers
In most cases, [
is a shell builtin and is equivalent to test
. However, like test
, it also exists as a standalone executable: that's the /bin/[
you saw. You can test this with type -a [
(on an Arch Linux system, running bash
):
$ type -a [
[ is a shell builtin
[ is /bin/[
So, on my system, I have two [
: my shell's builtin and the executable in /bin
. The executable is documented in man test
:
TEST(1) User Commands TEST(1)
NAME
test - check file types and compare values
SYNOPSIS
test EXPRESSION
test
[ EXPRESSION ]
[ ]
[ OPTION
DESCRIPTION
Exit with the status determined by EXPRESSION.
[ ... ]
As you can see in the excerpt of the man page quoted above, test
and [
are equivalent. The /bin/[
and /bin/test
commands are specified by POSIX which is why you'll find them despite the fact that many shells also provide them as builtins. Their presence ensures that constructs like:
[ "$var" -gt 10 ] && echo yes
will work even if the shell running them doesn't have a [
builtin. For example, in tcsh
:
> which [
/sbin/[
> set var = 11
> [ "$var" -gt 10 ] && echo yes
yes
-
5@AlexandruIrimiea what do you mean? A shell that doesn't have the
[
builtin is just a shell whose authors decided not to add one.tcsh
doesn't have a[
builtin for example.– terdon ♦Commented Jan 22, 2016 at 15:56 -
7@AlexandruIrimiea they're not "custom" shells. It's just that
bash
is only one of many programs (shells) that are designed to do similar jobs. Bash is one of the most popular but many systems ship with different default shells. Some of the better known ones aresh
,bash
,zsh
,dash
,ksh
,tcsh
,csh
andfish
. You can see the ones available on your system withcat /etc/shells
and a partial list here.– terdon ♦Commented Jan 22, 2016 at 16:06 -
1@JörgWMittag really? I knew that Ubuntu's
sh
isdash
but I thought the rescue system uses/bin/sh
not busybox. Are you sure?– terdon ♦Commented Jan 22, 2016 at 17:26 -
2However, there is indeed a busybox in initramfs, as evidenced from this question Commented Jan 22, 2016 at 17:48
-
1
That is used for condition testing in shell scripts. Another name of this program is test
:
if [ 1 -lt 2 ]; then ...
That looks like shell grammar but isn't. Usually [
is a shell builtin but probably as fallback it exists as an external command.
See the block "CONDITIONAL EXPRESSIONS" in man bash
.
-
1
[
is same command as test
. On some *nix systems, one is just a link to the other. For example, if you run:
strings /usr/bin/test
strings /usr/bin/[
you will see the same output.
Most sh-shells/posix-shells include builtin [
and test
commands.
The same is true for echo
. There is both a /bin/echo
command and a
builtin in most of shells. That it's the reason why sometimes you feel that, for example, echo
doesn't work the same way on different systems.
test
or [
return only an exit code of 0
or 1
. If the test was successful, the exit code is 0.
# you can use [ command but last argument must be ]
# = inside joke for programmers
# or use test command. Args are same, but last arg can't be ] :)
# so you can't write
# [-f file.txt] because [-f is not command and last argument is not ]
# after [ have to be delimiter as after every commands
[ -f file.txt ] && echo "file exists" || echo "file does not exist"
test -f file.txt && echo "file exists" || echo "file does not exist"
[ 1 -gt 2 ] && echo yes || echo no
test 1 -gt 2 && echo yes || echo no
# use external command, not builtin
/usr/bin/[ 1 -gt 2 ] && echo yes || echo no
You can also use [
with if
:
if [ -f file.txt ] ; then
echo "file exists"
else
echo "file does not exist"
fi
# is the same as
if test -f file.txt ; then
echo "file exists"
else
echo "file does not exist"
fi
But you can use if
with every command, if
is for testing exit code.
For example:
cp x y 2>/dev/null && echo cp x y OK || echo cp x y not OK
Or, using if
:
if cp x y 2>/dev/null ; then
echo cp x y OK
else
echo cp x y not OK
fi
You can get the same result using only the test
command to test the exit code which is saved to the variable stat
:
cp x y 2>/dev/null
stat=$?
if test "$stat" = 0 ; then
echo cp x y OK
else
echo cp x y not OK
fi
You can also use [[ ]]
and (( ))
for testing, but those are not the same as [
and test
, despite having almost the same syntax:
Finally, to find out what a command is, you can use:
type -a command
-
For comparing files you should rather use
cmp /usr/bin/[ /usr/bin/test
or maybe hashessha256sum /usr/bin/[ /usr/bin/test
but notstrings
. On my system (openSUSE Tumbleweed) BTW they are not the same (whyever). Commented Jan 23, 2016 at 19:37 -
I didn't mean byte comparing. In some *nix they are same also in byte level = linked. Posix test– kshjiCommented Jan 26, 2016 at 3:57