`unset` requires the variable name, not its expansion
`unset "$var"` unsets the variable named by the value of `$var`, not `$var` itself. SC2184 flags this common mix-up.
Problem
`unset` takes a variable *name* as its argument, not a value to be expanded. Writing `unset "$var"` first expands `$var` to its current value and then asks `unset` to remove the variable whose *name* matches that value — which is essentially never what you want, and usually unsets nothing (or the wrong variable, if the value happens to coincide with a real variable name). This mistake is subtle because bare `unset` still "runs successfully" with no error even when the argument does not resolve to any meaningful variable name, so the bug is silent unless you specifically check whether the intended variable still exists afterward.
Bad
myvar=hello
unset "$myvar" # tries to unset a variable literally named "hello"Good
myvar=hello
unset myvar # unsets the variable named myvar
# for array elements:
unset 'arr[3]'Explanation
Pass the bare variable name to `unset` (`unset myvar`), not its expansion. This also applies to array elements and associative array keys, where the index/key should be included literally, e.g. `unset 'arr[index]'`, quoted to prevent glob expansion of the brackets rather than to substitute a value.
Related
SC2178
SC2034
SC2154
When It Matters
unset takes variable names, not values, so unset "$var" removes whatever variable is named by the contents of var — and unset arr[0] with an unquoted index is subject to globbing, so a file named arr0 in the working directory changes what gets unset. The common form unset ${arr[@]} deletes variables named after the array’s contents, which is either a no-op or a very confusing bug.
Second Example
Note
Quoting the whole argument protects the brackets from pathname expansion, which is the part people most often miss.
Exceptions
Indirect unset through a name held in a variable is occasionally intentional in generic library code. Make it obvious with a comment, and prefer namerefs (declare -n) in Bash 4.3 and later, which express indirection explicitly.
Faq
Q
Why does unsetting an array element leave a gap?
A
Bash indexed arrays are sparse. Removing index 1 does not shift index 2 down; rebuild the array with arr=("${arr[@]}") if you need contiguous indices.
Q
How do I test whether a variable is set?
A
Use [ -v name ] in Bash, or the parameter expansion ${name+set}, which is empty only when the variable is unset.
Q
Does unset work on functions?
A
Yes, with unset -f name. Without a flag Bash removes a variable first if one exists by that name.