139

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?

1
  • 4
    Single square brackets are compatible across several shells, however a few of them, including Bash, support the preferred double square bracket. See BashFAQ/031 for more information. Also see help '[' Commented Jan 19, 2012 at 22:16

4 Answers 4

202

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 ... 
Sign up to request clarification or add additional context in comments.

6 Comments

@chepner: Why if $boolean_var ; then ... doesn't require brackets?
@misha, if your $boolean_var has the value "true" or "false", it works because you're running the command true or false.
if $boolean_var ; then ... does not work if $boolean_var is 0 or 1, see man true and man false.
@derFunk: It would work if you happened to have 0 and 1 commands in your $PATH -- but that would be ugly.
spellcheck doesn't like the brackets, but works with the test statement, in VSCode.
|
52

[ 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.)

4 Comments

spellcheck doesn't like the brackets, but works with the test statement, in VSCode.
@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.
plus one for the nervous argument.
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".
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.

4 Comments

There's nothing in the bash manpage that indicates that [ is implemented internally, I think that that's what [[ is for.
@PhilHibbs: I'm pretty sure [ is a built-in. That's why builtin [ works. [[ is somewhat different from [, it does different things.
@PhilHibbs: Look under the section SHELL BUILTIN COMMANDS of the bash man page. test expr and [ expr ] are listed together.
@PhilHibbs: Also, try type -a [
0

Without square brackets, GNU bash if supports a logical not operator

Apparently [1] if in GNU bash can accept a logical not operator ("!"):

if ! false ; then echo "! false is true" else echo "! false is false" fi if ! true ; then echo "! true is true" else echo "! true is false" fi 

displays

! false is true ! true is false 

[1] This isn't in the GNU documentation, so YMMV. This works in my macOS bash, which identifies itself as "GNU bash, version 3.2.57(1)-release (arm64-apple-darwin24)"

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.