122

Usually, I use square brackets in the if statement:

if [ "$name" = 'Bob' ]; then ...

But, when I check if grep succeeded I don't use the square brackets:

if grep -q "$text" $file ; then ...

When are the square brackets necessary in the if statement?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • 1
    Single square brackets are compatible across several shells, however a few of them, including Bash, support the preferred double square bracket. See [BashFAQ/031](http://mywiki.wooledge.org/BashFAQ/031) for more information. Also see `help '['` – Dennis Williamson Jan 19 '12 at 22:16

3 Answers3

184

The square brackets are a synonym for the test command. An if statement checks the exit status of a command in order to decide which branch to take. grep -q "$text" is a command, but "$name" = 'Bob' is not--it's just an expression. test is a command, which takes an expression and evaluates it:

if test "$name" = 'Bob'; then ...

Since square brackets are a synonym for the test command, you can then rewrite it as your original statement:

if [ "$name" = 'Bob' ]; then ...
chepner
  • 497,756
  • 71
  • 530
  • 681
46

[ is actually a command, equivalent (almost, see below) to the test command. It's not part of the shell syntax. (Both [ and test, depending on the shell, are often built-in commands as well, but that doesn't affect their behavior, except perhaps for performance.)

An if statement executes a command and executes the then part if the command succeeds, or the else part (if any) if it fails. (A command succeeds if it exits with a status ($?) of 0, fails if it exits with a non-zero status.)

In

if [ "$name" = 'Bob' ]; then ...

the command is

[ "$name" = 'Bob' ]

(You could execute that same command directly, without the if.)

In

if grep -q "$text" $file ; then ...

the command is

grep -q "$text" $file

man [ or man test for more information.

FOOTNOTE: Well, the [ command is almost equivalent to the test command. The difference is that [ requires ] as its last argument, and test does not -- and in fact doesn't allow it (more precisely, test doesn't treat a ] argument specially; for example it could be a valid file name). (It didn't have to be implemented that way, but a [ without a matching ] would have made a lot of people very very nervous.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • spellcheck doesn't like the brackets, but works with the test statement, in VSCode. – johnrubythecat Jul 22 '18 at 15:33
  • 1
    @johnrubythecat: What "spellcheck" are you referring to? If it's something intended to spell check English text, then of course it's not going to be happy about shell syntax. – Keith Thompson Jul 22 '18 at 23:28
  • 4
    plus one for the `nervous` argument. – Timo Aug 06 '20 at 19:03
  • I think we are all pretty nervous having lived with shell syntax all these years. If I saw an omitted closing bracket it would just be "one more thing". – gbarry Jul 25 '22 at 18:49
11

The best way to think of the [ ... ] syntax, is to consider [ to be a program - which it is!

Check this out:

~ $ ls /usr/bin/\[ 
/usr/bin/[

on the other hand, you're probably not using that version of it since bash also provides [ as a shell built-in.

Anyway, to answer your question: What if does is run the command you give it and see it the return value is 0 or not. You use [ to do other, more interesting comparisons such as string comparisons. See man [ and man bash.

cha0site
  • 10,517
  • 3
  • 33
  • 51
  • There's nothing in the bash manpage that indicates that `[` is implemented internally, I think that that's what `[[` is for. – PhilHibbs Sep 17 '12 at 14:51
  • @PhilHibbs: I'm pretty sure `[` is a built-in. That's why `builtin [` works. `[[` is somewhat different from `[`, it does different things. – cha0site Sep 22 '12 at 16:34
  • 1
    @PhilHibbs: Look under the section SHELL BUILTIN COMMANDS of the `bash` man page. `test expr` and `[ expr ]` are listed together. – chepner Oct 09 '12 at 13:09
  • 1
    @PhilHibbs: Also, try `type -a [` – Keith Thompson Apr 21 '14 at 22:17