Use "${var:?}" to ensure this never expands to /*
When `$dir` is empty, `rm -rf "$dir"/*` becomes `rm -rf /*`. Guard with `${dir:?}`.
Problem
An empty variable turns a path like `"$root/cache"` into `"/cache"` — and `"$root"/*` into `/*`. With `rm -rf`, that's a fleet-deleting bug. ShellCheck flags any rm/chmod/chown command whose path could collapse to root.
Bad
dir=$1
rm -rf "$dir"/*Good
dir=$1
rm -rf "${dir:?dir is unset or empty}"/*Explanation
`${var:?message}` aborts the script with the given message when `var` is unset or empty. It is one line of defense that converts a catastrophic bug into a clear error.
When It Matters
rm -rf "$dir/" is one unset variable away from rm -rf "/". Scripts run in CI, in containers as root, and in cron jobs where an environment variable that exists locally is simply absent — and the resulting command deletes the root filesystem without a single warning. This is not theoretical: it is the single most-cited class of catastrophic shell bug, and it has taken out production hosts and shipped in installers from well-known vendors.
Second Example
Note
The ${var:?} form fails the command rather than expanding to nothing, which converts a silent catastrophe into an ordinary error message.
Exceptions
There is no good reason to skip the guard on a recursive delete. If the variable is a literal constant assigned two lines above, the risk is lower, but the guard costs three characters and survives the refactor that later makes the value dynamic.
Faq
Q
What exactly does ${var:?} do?
A
If the variable is unset or empty, the shell prints an error and exits (or, in an interactive shell, returns to the prompt) rather than substituting an empty string.
Q
Does set -u make the guard unnecessary?
A
It catches unset variables but not empty ones. ${var:?} catches both, so the two are complementary.
Q
Why add -- before the path?
A
It stops a path beginning with a dash being parsed as an option. It is cheap insurance on every rm, cp, and mv that takes a variable path.