Skip to content

/errors/bash/too-many-arguments-in-test

bash: [: too many arguments

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

[: too many arguments is printed by the [ command (the same builtin as test) when it receives more words than any test form accepts. The usual reason is an unquoted variable that contains spaces: bash splits it into several words before [ sees them. Quote the variable or switch to [[ ... ]].

Reproduce it

bash
name="john smith"
if [ $name = "john smith" ]; then
  echo "match"
else
  echo "no match"
fi
echo "status: $?"

Output

bash: line 2: [: too many arguments
no match
status: 0

Without quotes, the test becomes [ john smith = "john smith" ], which is four arguments before ]. No valid test takes four arguments of that shape, so [ reports the error and returns status 2, and if takes the else branch.

How [ counts its arguments

[ is a command, so bash first performs word splitting and pathname expansion on every unquoted argument. The test then accepts a fixed set of shapes: one argument (true if non-empty), two (a unary operator and its operand, or ! and one argument), three (a binary operator between two operands) and so on up to a limited number with !, parentheses and the legacy -a and -o operators. Anything else is an error.

The empty-variable case fails differently: [ -n $x ] with an empty x becomes [ -n ], which is true because a single non-empty word is a valid test. Quoting avoids both problems.

Cause 1: unquoted variable with spaces

Quote the variable so it stays a single argument.

bash
name="john smith"
if [ "$name" = "john smith" ]; then
  echo "match"
fi

Output

match

Cause 2: a glob inside the test

[ -f *.txt ] expands the glob first. With two files it becomes [ -f a.txt b.txt ] and fails. Test the files one by one in a loop, or check for matches with compgen -G "*.txt".

Cause 3: [[ ]] avoids the problem in bash

The [[ keyword is parsed by the shell, so it does not split words or expand globs on the left side.

bash
name="john smith"
if [[ $name = "john smith" ]]; then
  echo "match"
fi

Output

match

Prefer [[ ]] in scripts that start with #!/usr/bin/env bash. Use quoted [ ] when the script must run under plain sh.

Prevent it

Quote all variable expansions unless you intend splitting, and run shellcheck on scripts: it reports unquoted variables in tests as SC2086. Use set -u (see the unbound variable page) to catch unset variables, and avoid -a and -o; chain two tests with && and ||.

FAQ

Is [ a command or syntax?

In bash, [ is a builtin command that is a synonym of test, and the closing ] is its last argument. That is why spaces around it are required and why unquoted words become separate arguments.

What exit status does the failed test return?

The error exits with status 2, which an if statement treats as false, so the else branch runs silently unless you read stderr.

Does [[ ]] work in sh scripts?

No. [[ ]] is a bash, ksh and zsh feature. A script started with #!/bin/sh on a POSIX shell such as dash must use [ ] with quoted variables.

Sources