Shell builtins · bash builtin
unset
Remove shell variables, array elements or functions, so they no longer exist rather than being empty.
unset [-f | -v | -n] NAME...
unset NAME deletes a variable: afterward it is not set at all, which is different from being
set to an empty string. The distinction matters to ${var-default}, [[ -v var ]] and set
-u, and an unset variable also disappears from the environment of child processes if it was
exported.
The same builtin removes functions (unset -f name) and single array elements (unset
'arr[2]'). Removing an element leaves a gap in the indices rather than shifting the others
down, which surprises people used to lists in other languages.
Without an option, bash tries a variable first and then a function of that name. In scripts,
say which you mean with -v or -f. Read-only variables, such as those made with readonly
or declare -r, cannot be unset.
Examples
Remove a variable
name="Alice"
unset name
echo "name=[$name]"
echo "${name-it is unset}"
name=[] it is unset
After unset, expanding name gives an empty string. ${name-default} (no colon) uses
the default only when the variable is unset, which shows it really is gone.
Empty is not the same as unset
a=""
unset b
[[ -v a ]] && echo "a is set (to an empty string)"
[[ -v b ]] || echo "b is not set"
echo "a: [${a-default}] b: [${b-default}]"
a is set (to an empty string) b is not set a: [] b: [default]
-v tests whether a variable exists. ${var-default} substitutes only for unset
variables, while ${var:-default} would also replace the empty string.
Remove a variable from the environment of child processes
export DEBUG=true
bash -c 'echo "child: DEBUG=[$DEBUG]"'
unset DEBUG
bash -c 'echo "child: DEBUG=[$DEBUG]"'
child: DEBUG=[true] child: DEBUG=[]
Unsetting an exported variable removes it from the environment too. To hide it from
one command only, use env -u DEBUG cmd.
Remove a function with -f
ls() { echo "fake ls"; }
ls scripts
unset -f ls
ls scripts
fake ls backup.sh greet.sh
Once the function is gone, ls resolves to the real program again.
Remove one array element
fruits=(apple banana cherry date)
unset 'fruits[1]'
echo "values: ${fruits[*]}"
echo "indices: ${!fruits[*]}"
echo "count: ${#fruits[@]}"
values: apple cherry date indices: 0 2 3 count: 3
banana is removed, but the other elements keep their indices, so there is now a gap
at 1. Quote 'fruits[1]' so the brackets are not taken as a glob pattern matching a file
named fruits1. Re-pack with fruits=("${fruits[@]}") if you need contiguous indices.
Remove a whole array
list=(a b c)
unset list
echo "elements left: ${#list[@]}"
elements left: 0
unset name without an index removes the entire array.
Read-only variables cannot be unset
readonly VERSION=2.4.1
unset VERSION
echo "status $?, VERSION=$VERSION"
/bin/bash: line 2: unset: VERSION: cannot unset: readonly variable status 1, VERSION=2.4.1
bash refuses and returns 1. Read-only variables last until the shell exits.
Unset variables trip set -u
set -u
tmpdir=/tmp/work
unset tmpdir
echo "removing $tmpdir"
/bin/bash: line 4: tmpdir: unbound variable
With set -u, expanding a variable after it has been unset is a fatal error, so the
script stops instead of running a command with an empty path. bash 5.2 exits with 127
here.
Common pitfalls
unset arr[1]without quotes: if a file namedarr1exists, the glob expands to it and the wrong name is unset. Writeunset 'arr[1]'.Assuming
unseton an array element shifts the rest down. Indices stay as they were;${#arr[@]}drops, but the highest index does not.unsetwith no option removes a variable of that name if one exists, and a function only if not. Useunset -ffor functions to avoid deleting a variable by accident.Setting a variable to empty (
VAR=) when a program checks whether it is defined; some tools treat an emptyHTTP_PROXYorGIT_DIRdifferently from an absent one. Useunset.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
unset,-fand-vare POSIX. Array elements and-n(namerefs) are bash features.
Options worth knowing
A selection, described in our own words. For the full list, see bash(1), SHELL BUILTIN COMMANDS.
| Option | What it does |
|---|---|
-v | Treat each name as a variable. |
-f | Treat each name as a shell function. |
-n | If the name is a nameref, unset the reference itself, not the variable it points to. |
Related
exportMark shell variables (or bash functions) to be passed to every program the shell starts.declareCreate variables with attributes (array, associative array, integer, read-only, exported), or show how variables are defined.setTurn shell options such as -e, -u, -x and pipefail on or off, and replace the positional parameters.envPrint the environment, or run a command with a modified environment.localDeclare variables inside a function that disappear when it returns, leaving any global of the same name untouched.- VariablesAssigning and reading shell variables, the no-spaces rule, braces, unset vs empty, scope, readonly, and the special variables bash sets for you.
- ArraysIndexed arrays in bash, creating, reading, appending, looping, slicing and removing elements, and using them to build command lines safely.
- Parameter expansionThe ${...} operators for defaults, lengths, substrings, trimming prefixes and suffixes, search and replace, and case conversion, without calling sed or cut.