Skip to content

/errors/bash/test-missing-closing-bracket

bash: [: missing `]'

verified onenvironmentlocal · linux 6.18.44-fc-v153 x64 · GNU bash 5.2.21updated
tool
Bash
exit code
2
versions
bash 4.x, bash 5.x
os
linux, macos, windows

[: missing ]'means bash ran the[command and none of its arguments was a lone]. In bash, [is not punctuation: it is a command, a synonym oftest, and its **last argument must be ]**. If the bracket is attached to another word, or never typed, [complains and returns an error status, theiftreats the condition as false and the script quietly takes theelse` path.

Reproduce the error

The then keyword follows the semicolon, but the test was never closed:

bash
x=abc
if [ "$x" = abc; then
  echo "match"
fi
echo "after the if"

Output

bash: line 2: [: missing `]'
after the if

The message names the line of the test. Interactive shells omit line N: and print bash: [: missing ]'`. Note that the script continues: the failed test is only a false condition.

Why it happens

[ "$x" = abc ] is parsed like any command line: the words are [, "$x", =, abc and ]. Bash needs the final word to be exactly ]. Three typical mistakes break that rule:

  1. No space before the bracket. [ "$x" = abc] passes the single word abc], so the last argument is not ].
  2. The bracket is missing. This happens when a condition is edited or a [[ ... ]] line is cut halfway.
  3. A separator sits in the wrong place. ; ends a command, so everything after it belongs to the next command, and the [ before it stays unclosed.

The same rule explains why [ -f "$file" ] needs spaces just inside the brackets, and why [ $x = abc ] with an empty x produces a different error, unary operator expected or too many arguments.

Fix it

Close the test with a standalone ] before the semicolon:

bash
x=abc
if [ "$x" = abc ]; then
  echo "match"
fi

Output

match

For bash scripts the [[ ]] form is safer, because the shell parses it as syntax and does not word-split variables:

bash
x=abc
if [[ $x == abc ]]; then
  echo "match"
fi

Output

match

Confirm the fix by running the script again: the error line disappears and the branch you expect runs.

Check scripts before running them

bash -n script.sh parses the file without running it, and it does not report this error, because a missing ] is a runtime error of the [ command, not a syntax error. A linter such as shellcheck is the usual way to catch missing spaces around brackets before the script runs. Quote variables inside [ ] as a habit: it avoids the neighbouring errors with empty values and spaces.

FAQ

Why does bash need spaces inside [ ]?

[ is not syntax, it is a command (a builtin, and also /usr/bin/[). Its arguments are separated by spaces, and the last argument must be exactly ]. Without the space the shell never sees a separate ] word.

Is [[ ]] different from [ ]?

Yes. [[ is a shell keyword with its own parser, so it does not split unquoted variables and it supports && and ||. It exists in bash, zsh and ksh but not in plain POSIX sh.

Why does the script keep running after the error?

The failed [ returns a non-zero status, so the if condition is false and bash skips the branch. Only set -e or an explicit check on the status stops the script.

Sources