What is the purpose of square bracket executable

8,117

Solution 1

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

Solution 2

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.

Solution 3

[ 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
Share:
8,117

Related videos on Youtube

Alexandru Irimiea
Author by

Alexandru Irimiea

Updated on September 18, 2022

Comments

  • Alexandru Irimiea
    Alexandru Irimiea almost 2 years

    I see there is an executable called "[" in /usr/bin. What is its purpose?

    enter image description here

  • dr_
    dr_ over 8 years
  • Alexandru Irimiea
    Alexandru Irimiea over 8 years
    Well, how is it possible for shell to not have a [ builtin?
  • terdon
    terdon over 8 years
    @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.
  • Alexandru Irimiea
    Alexandru Irimiea over 8 years
    OK, now I understand. I didn't know there can be custom shells.
  • terdon
    terdon over 8 years
    @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 are sh, bash, zsh, dash, ksh, tcsh, csh and fish. You can see the ones available on your system with cat /etc/shells and a partial list here.
  • Jörg W Mittag
    Jörg W Mittag over 8 years
    @AlexandruIrimiea: considering that your screenshot looks very Ubuntu-y, you are already using at least two different shells: the default shell for scripts on Ubuntu is dash, bash is only the default for interactive logins, and if for some reason your boot fails early on, or you do a non-standard installation, you will be dropped into ash (or more precisely the BusyBox implementation of it).
  • terdon
    terdon over 8 years
    @JörgWMittag really? I knew that Ubuntu's sh is dash but I thought the rescue system uses /bin/sh not busybox. Are you sure?
  • terdon
    terdon over 8 years
    @JörgWMittag I just checked on an Ubuntu box and there's no busybox installed by default. What you describe might (I haven't checked) happen during installation but not on failed boot. Since there's no busybox installed, it's safe to assume that the rescue shell will be /bin/sh, so dash on Ubuntu.
  • Jörg W Mittag
    Jörg W Mittag over 8 years
    Hmm … I think it's in the initramfs, so it wouldn't be installed on the system. But I could very well be misremembering and it's only in the netinstaller, or maybe it's Debian, not Ubuntu.
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy over 8 years
    However, there is indeed a busybox in initramfs, as evidenced from this question
  • Wildcard
    Wildcard over 8 years
    @AlexandruIrimiea, regarding what commands it is necessary to have built in and what commands may or may not be built in, see this post.
  • vonbrand
    vonbrand over 8 years
    @AlexandruIrimiea, one of the fun facts on Unix is that the program with with the user usually interacts directly is just a plain, run-of-the-mill program. And not even one very hard to write, at least in simple incarnations (writing a simple shell is a popular homework assignment). As a result, everybody and aunt Tillie wrote their own, and there is a veritable plethora to select from. sh (the "original" Bourne shell) is mandated to be available by POSIX, there are truly exotic shells around as alternatives.
  • Hauke Laging
    Hauke Laging over 8 years
    For comparing files you should rather use cmp /usr/bin/[ /usr/bin/test or maybe hashes sha256sum /usr/bin/[ /usr/bin/test but not strings. On my system (openSUSE Tumbleweed) BTW they are not the same (whyever).
  • kshji
    kshji over 8 years
    I didn't mean byte comparing. In some *nix they are same also in byte level = linked. Posix test