Bash error: unary operator expected
The "[: -eq: unary operator expected" error appears when one side of a `[ ]` test is empty. Quote the variable or default it.
Error String
bash: [: -eq: unary operator expected
Tldr
When `[ $x -eq 1 ]` and `$x` is empty, Bash sees `[ -eq 1 ]` — a unary operator with no operand. Quote the variable so the empty case becomes `[ "" -eq 1 ]`, which is a clean error you can handle.
Cause
Unquoted empty variables disappear from the argument list. `[` then thinks the next token is the only operand, which is the wrong shape.
Repro
if [ $x -eq 1 ]; then ... # x empty -> [: -eq: unary operator expectedFix
if [ "${x:-0}" -eq 1 ]; then ...
# Or use (( )) which treats empty as 0:
if (( x == 1 )); then ...Explanation
Same root cause as "integer expression expected" and "too many arguments" — always quote variables in `[ ]` tests, or use `[[ ]]` / `(( ))` which are Bash-only but parse cleanly.
Related Shellcheck
SC2086
Faq
Q
What is the x-prefix trick?
A
`[ "x$var" = "xvalue" ]` guarantees a non-empty operand in ancient shells. Quoting is sufficient in any modern shell.
Q
Why did an unquoted file test return true instead of erroring?
A
`[ -f ]` degenerates to a non-empty-string test on the literal `-f`, which is always true.
Deep Dive
Heading
An empty expansion removes the operand
Body
The mirror image of the binary-operator error: `[ $var = value ]` with an empty `$var` becomes `[ = value ]`, and the test finds an operator with nothing on the left. Quoting fixes it — `[ "$var" = value ]` becomes `[ "" = value ]`, a perfectly valid comparison that simply returns false. The same happens for a missing positional parameter, so guard `$#` before touching `$1`.
Heading
File tests on empty paths
Body
`[ -f $path ]` with an empty `$path` collapses to `[ -f ]`, which tests whether the string `-f` is non-empty and quietly returns true — an even worse outcome than an error. Always quote path expansions and reject empty values explicitly. In Bash, `[[ -f $path ]]` avoids the splitting problem entirely, which is the main reason to prefer it in scripts that never need POSIX `sh`.
Checklist
Quote every expansion inside `[ ]`.
Check `$#` before comparing positional parameters.
Reject empty values with `[ -z "$var" ]` and a clear message.
Prefer `[[ ]]` in Bash-only scripts.