Skip to content
Linux Basics: Give Bash Variables Explicit Attributes

Linux Basics: Give Bash Variables Explicit Attributes

October 22, 2026

A variable can have rules that apply to later assignments: a fixed configuration value, automatic lowercase conversion, or integer arithmetic. Use readonly and declare to make those rules visible, and check where they stop being useful.

These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. All example values belong to the script’s Bash process. No configuration files or terminal variables are changed.

Prepare a scratch directory

You need Bash, a text editor, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this directory before running it. The guards stop setup if it fails; invoking bash explicitly avoids changing executable permissions. No administrator access is needed.

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

1. Protect a configuration value against accidental reassignment

Save this as attributes-readonly.sh:

#!/usr/bin/env bash
readonly report_format=csv
declare -p report_format
if (report_format=json) 2>/dev/null; then
  printf 'Unexpected reassignment\n'
  exit 1
else
  printf 'Reassignment refused\n'
fi
if unset report_format 2>/dev/null; then
  printf 'Unexpected removal\n'
  exit 1
else
  printf 'Removal refused\n'
fi
printf 'Format remains: %s\n' "$report_format"

Run it:

bash attributes-readonly.sh

Output:

declare -r report_format="csv"
Reassignment refused
Removal refused
Format remains: csv

declare -p shows the value together with its attributes; -r marks this one read-only. Both the attempted assignment and unset fail, and the final line verifies that the original setting survived.

The failing assignment is placed in a subshell because a read-only assignment error can terminate a non-interactive shell. Its diagnostic is suppressed only to keep this controlled transcript stable. Read-only values help catch programming mistakes, but do not hide data or provide a security boundary. Avoid dumping variable values with declare -p when they may contain credentials.

2. Normalize later text assignments

Save this as attributes-case.sh:

#!/usr/bin/env bash
export LC_ALL=C
declare -l channel='OPS'
printf 'Initial channel: %s\n' "$channel"
channel='SUPPORT'
printf 'Updated channel: %s\n' "$channel"
declare +l channel
channel='MiXeD'
printf 'After removing attribute: %s\n' "$channel"

Run it:

bash attributes-case.sh

Output:

Initial channel: ops
Updated channel: support
After removing attribute: MiXeD

The lowercase attribute affects both the initial value and a later assignment. Removing it with declare +l allows the mixed-case third value through unchanged. This differs from converting a string once: the variable itself carries a continuing assignment rule until that rule is removed.

The example uses ASCII text and the C locale for predictable results. Case conversion is not validation: an unexpected channel name remains unexpected after lowercasing. Use an explicit allowlist when only certain values are acceptable. This feature requires Bash 4 or later.

3. Keep integer evaluation separate from ordinary text

Save this as attributes-integer.sh:

#!/usr/bin/env bash
declare -i attempts=2
attempts='attempts + 3'
printf 'Arithmetic assignment: %s\n' "$attempts"
declare -p attempts
declare +i attempts
attempts='2 + 3'
printf 'After removing attribute: %s\n' "$attempts"

Run it:

bash attributes-integer.sh

Output:

Arithmetic assignment: 5
declare -i attempts="5"
After removing attribute: 2 + 3

The first assignment evaluates the known expression because attempts has the integer attribute. After declare +i, the same variable stores ordinary text instead. This is useful when reading an existing script: the assignment syntax alone does not tell you whether a value will be treated as text.

Only trusted literal arithmetic is used here. declare -i is not an input validator; Bash arithmetic interprets expressions and variable references. Do not pass arbitrary user input into it. Validate the intended numeric format and range before doing calculations, and remember that Bash arithmetic uses fixed-width integers rather than arbitrary precision.

Keep in mind

Most attributes shown here can be removed with a plus option, but read-only cannot be undone with declare +r. Also, declare inside a function normally creates a local variable. Choose the scope deliberately instead of assuming it will modify a global setting. The examples use top-level declarations to keep that distinction out of the main flow.

Clean up

In the same terminal, remove only the named practice files, return to your original directory, and remove the empty scratch directory:

rm -- attributes-readonly.sh attributes-case.sh attributes-integer.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

References

Acknowledgements

This post was created with assistance from AI.

Last updated on