← Back to Bash Course | Chapter 2: Variables & Types | Lesson 8 of 13

readonly and unset

readonly locks a variable so it can never be changed again, and unset removes a variable completely as if it had never been assigned.

Declaring a Constant with readonly

readonly NAME=value creates a variable and marks it immutable in one step, so any later attempt to reassign it fails with an error message rather than silently changing the value. This is useful for values that represent true constants in your script, like a fixed configuration path.

Example: Declaring a Constant with readonly

bash
#!/bin/bash
readonly MAX_RETRIES=3
echo "Max retries allowed: $MAX_RETRIES"

Attempting to Change a readonly Variable

If you try to reassign a readonly variable, Bash prints an error to stderr and refuses the assignment, but by default the script continues running afterward (it does not halt automatically). Wrapping the attempt so the script can react to failure lets you handle this gracefully.

Example: Attempting to Change a readonly Variable

bash
#!/bin/bash
readonly LOCKED="original"
if ! (LOCKED="changed") 2>/dev/null; then
    echo "As expected, LOCKED could not be reassigned"
fi
echo "LOCKED is still: $LOCKED"

Removing a Variable with unset

unset NAME deletes a variable's definition entirely, so afterward referencing it behaves as if it was never assigned (expanding to an empty string, or triggering an error under set -u). This differs from assigning an empty string, which keeps the variable defined but empty.

Example: Removing a Variable with unset

bash
#!/bin/bash
temp_value="scratch data"
echo "Before unset: [$temp_value]"
unset temp_value
echo "After unset: [$temp_value]"
if [ -z "${temp_value+set}" ]; then
    echo "temp_value is completely unset"
fi

Empty String vs Truly Unset

${var+set} expands to the literal word set if var is defined at all (even as an empty string), and to nothing if it is completely unset. This parameter expansion is the standard way to tell the two states apart, which a plain -z check on the value cannot do.

Example: Empty String vs Truly Unset

bash
#!/bin/bash
empty_var=""
unset gone_var
echo "empty_var defined? ${empty_var+yes}"
echo "gone_var defined? ${gone_var+yes}"
Common Mistakes
  1. Trying to change or unset a readonly variable and expecting it to silently work; Bash refuses and prints an error, and in a non-interactive script this can even cause the script to exit depending on settings.
  2. Confusing unset var with setting a variable to an empty string, var=""; an empty-string variable is still set (defined) and passes -v or ${var+x} tests differently than a fully unset one.
  3. Assuming readonly only prevents reassignment via =; it also blocks unset on that same variable within the same shell.
Chapter Summary
  • readonly NAME=value makes a variable's value immutable for the rest of the shell's life; attempting to reassign it produces an error.
  • unset NAME completely removes a variable's definition, distinct from setting it to an empty string.
  • A readonly variable cannot later be unset in the same shell session.
  • Both are useful for defensive scripting: readonly protects constants, unset cleans up temporary variables or ensures a fresh state.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.