/errors/bash/test-missing-closing-bracket
bash: [: missing `]'
- 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:
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:
- No space before the bracket.
[ "$x" = abc]passes the single wordabc], so the last argument is not]. - The bracket is missing. This happens when a condition is edited or a
[[ ... ]]line is cut halfway. - 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:
x=abc
if [ "$x" = abc ]; then
echo "match"
fiOutput
match
For bash scripts the [[ ]] form is safer, because the shell parses it as syntax and does not word-split variables:
x=abc
if [[ $x == abc ]]; then
echo "match"
fiOutput
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.
Related errors
too many argumentsappears when an unquoted variable expands to several words.integer expression expectedappears when-eq,-ltor similar compare a non-number.- The file existence page shows correct
[ -f ]and[ -d ]tests.
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.