Bash Parameter Expansion: Two Quirks That Slip Through Code Reviews
Here's a pair of bash parameter expansion behaviors that I've seen slip through code reviews and cause intermittent failures in production scripts. Small stuff, but worth knowing.
${var:-default} vs ${var-default}
This trips people up constantly. The colon matters:
var="" # var is set, but empty
echo "${var:-default}" # prints: default
echo "${var-default}" # prints: (empty)
With the colon, bash checks if the variable is unset OR empty. Without the colon, it only checks if the variable is unset. So an empty string gets treated as "use the default" with :-, but as "use the empty value" without.
In practice, this matters most when you're handling environment variables or config values that might legitimately be empty:
# Safe: use default only when truly absent
HOME_DIR="${HOME:-/root}"
# Unsafe: empty HOME would still use /root
HOME_DIR="${HOME-/root}"
The colon form is almost always what you want when setting defaults for potentially-empty values.
[[ -v var ]] vs [[ -n $var ]]
Another subtle one. -v checks if a variable is declared (and non-empty in bash 4.2+). -n checks if the value is non-empty.
var="" # declared but empty
[[ -v var ]] # true (var exists)
[[ -n $var ]] # false ($var expands to empty string)
[[ -n "$var" ]] # false (same, quoted or not)
The -n "$var" version is actually checking if the quoted string is non-empty, which is always false for an empty variable. But -v correctly identifies that the variable exists, regardless of its value.
This shows up when checking if optional flags were passed:
VERBOSE="" # passed but empty
[[ -v VERBOSE ]] && echo "verbose mode" # correctly matches
[[ -n $VERBOSE ]] && echo "verbose mode" # misses it
For declared/empty check: use -v. For "has non-empty value" check: use -z or -n "$var".
Practical Takeaway
When writing scripts that handle config or environment variables, prefer ${var:-default} and [[ -v var ]]. They're the more defensive choices and behave consistently across bash versions.
Top comments (0)