84

I was trying to write a Bash script that uses an if statement.

if[$CHOICE -eq 1];

The script was giving me errors until I gave a space before and after [ and before ] as shown below:

if [ $CHOICE -eq 1 ];

My question here is, why is the space around the square brackets so important in Bash?

that other guy
  • 116,971
  • 11
  • 170
  • 194
Shash
  • 4,160
  • 8
  • 43
  • 67
  • 8
    The general syntax is `if command; then commands_if_exit_code_is_0; else commands_if_exit_code_is_nonzero; fi;`. *`command`* can be any command, and `[` is just one of them. – Benoit Mar 06 '12 at 09:43
  • 1
    Related: https://stackoverflow.com/questions/4977367/why-equal-to-operator-does-not-work-if-its-not-surrounded-by-space (you need spaces around the operator, too). – tripleee Oct 02 '17 at 04:37
  • 1
    See this related post: [Is double square brackets preferable over single square brackets in Bash?](https://stackoverflow.com/q/669452/6862601). – codeforester Aug 16 '18 at 02:28
  • https://stackoverflow.com/questions/2268104/command-not-found-error-in-bash-variable-assignment/2268117#2268117 – William Pursell Nov 05 '18 at 16:34
  • 1
    If `$CHOICE` is `"foo"`, you are attempting to run the command `["foo"`. – tripleee Jan 30 '20 at 18:20
  • 1
    In Bash, `[[` obeys the same requirements; you need spaces on both sides, and the command needs to end with `]]`. The doubled version is somewhat more versatile and robust; see the link by @codeforester above for a more nuanced discussion. – tripleee Mar 30 '21 at 04:24

5 Answers5

99

Once you grasp that [ is a command, a whole lot becomes clearer!

[ is another way to spell "test".

help [

However while they do exactly the same, test turns out to have a more detailed help page. Check

help test

...for more information.


Furthermore note that I'm using, by intention, help test and not man test. That's because test and [ are shell builtin commands nowadays. Their feature set might differ from /bin/test and /bin/[ from coreutils which are the commands described in the man pages.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • 7
    and originally, it was at `/usr/bin/[` and was a hardlink to `/usr/bin/test`, when invoked as `[` you should include a closing brace as last argument. Now it's a shell builtin. – Benoit Mar 06 '12 at 09:41
  • 3
    Note that they are not quite "exactly" the same. `[` requires that its last argument be `]`. – William Pursell Jul 15 '19 at 18:29
19

From another question:

A bit of history: this is because '[' was historically not a shell-built-in but a separate executable that received the expresson as arguments and returned a result. If you didn't surround the '[' with space, the shell would be searching $PATH for a different filename (and not find it) . – Andrew Medico Jun 24 '09 at 1:13

Community
  • 1
  • 1
Cameron
  • 1,675
  • 11
  • 12
9

[ is a command and $CHOICE should be an argument, but by doing [$CHOICE (without any space between [ and $CHOICE) you are trying to run a command named [$CHOICE. The syntax for command is:

command arguments separated with space
Jahid
  • 21,542
  • 10
  • 90
  • 108
2

It's worth noting that [ is also used in glob matching, which can get you into trouble.

$ echo [12345]
[12345]
$ echo oops >3
$ echo [12345]
3
Daniel
  • 137
  • 1
  • 4
  • In case it's not obvious what's going on here, in the first case you don't happen to have any file which matches the wildcard expression `[12345]` so the shell leaves it unexpanded. But when there is a file named `3`, that's what the wildcard expands to. – tripleee Mar 17 '23 at 13:52
2

[ is a test command. So it requires space.

Prince John Wesley
  • 62,492
  • 12
  • 87
  • 94