Use `-n` / `-z` instead of `! -z` / `! -n`

Test idioms have direct positive forms — prefer `[ -n "$x" ]` over `[ ! -z "$x" ]`.

Problem

Negating a negative test ("the string is not empty") is harder to read than the equivalent positive test. Bash provides direct primitives for both.

Bad

if [ ! -z "$name" ]; then ...
if [ ! -n "$name" ]; then ...

Good

if [ -n "$name" ]; then ...   # non-empty
if [ -z "$name" ]; then ...   # empty

Explanation

`-n` tests "non-empty" and `-z` tests "empty". They are the canonical idioms. As a bonus, both work identically in `[ ]` and `[[ ]]`.

When It Matters

! -z reads as "not empty", which is a double negative your reader has to unpack every time, and in a compound condition it is easy to attach the ! to the wrong term. [ ! -z "$x" -a -f "$x" ] parses differently from what most people expect, while [ -n "$x" ] && [ -f "$x" ] cannot be misread. The practical risk is not the test itself but the edits that follow it: a negated test is where off-by-one logic errors accumulate during maintenance.

Second Example

Note

Always quote the operand. An unquoted empty variable makes [ -n $x ] collapse to [ -n ], which is true — the exact opposite of the intent.

Exceptions

Negation is fine when there is no direct opposite operator, for example [ ! -f "$path" ] for "not a regular file". The rule targets only -z and -n, which are each other’s inverse.

Faq

Q

Why does [ -n $x ] return true for an empty variable?

A

Unquoted, the empty value disappears entirely, leaving [ -n ] — a single-argument test that is true because the string "-n" is non-empty. Quoting fixes it.

Q

Is [[ ]] safer here?

A

Yes, [[ ]] does not word-split its operands, so [[ -n $x ]] behaves correctly even unquoted. It is a Bash extension, not available in POSIX sh.

Q

Are -a and -o safe to use?

A

They are deprecated and ambiguous with operands that look like operators. Use separate tests joined with && and ||.