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 ... # emptyExplanation
`-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 ||.