Using Bash Declare: Gateway For Effective Variable Management
The declare built-in allows you to explicitly declare variables in bash scripts with specific attributes and control variable types, scope, and behavior.

Ever wondered how to make your bash scripts more robust and professional? The declare command in bash is your secret weapon for proper variable management!
Alright! So, variables in bash don't have any types and you can simply use them as name=value
. That's not surprising.
What you might not know is that you can control variable types, scope, and behavior by using declare
with your variables.
Interesting, right?
What is Declare in Bash?
The declare built-in command in bash allows you to explicitly declare variables with specific attributes. Think of it as giving your variables special properties that control how they behave.
The syntax for declare is simple:
declare [options] [variable[=value]]
If you use it without any options, it will be the same as regular variable assighnment.
# Simple variable assignment
name="John"
# Using declare (equivalent but more explicit)
declare name="John"
The magic happens with the options that define variable attributes, as they open up a world of possibilities! Stay with me to see the incredible power of this lesser known bash command.
Making variables read-only (-r)
Want to create constants that can't be accidentally modified? Use the -r
flag:
declare -r var=value
Here's an example:
declare -r API_URL="https://api.example.com"
declare -r MAX_RETRIES=3
# This will fail with an error because API_URL is readonly variable
API_URL="https://malicious.com"
Define integer variables (-i)
Force variables to behave as integers for mathematical operations in bash:
declare -i int_var=123
$(( ))
or $[ ]
. Now that's something, right?Here's a proper example:
declare -i counter=10
declare -i result
counter=counter+5 # Works without $ or (( ))
echo $counter # Output: 15
result=counter*2 # Mathematical operations work directly
echo $result # Output: 30
This is a good way to validate user input of your bash script.
declare -i user_input
read -p "Enter a number: " user_input
if [[ $user_input -eq 0 ]] && [[ "$user_input" != "0" ]]; then
echo "Invalid input! Please enter a number."
else
echo "You entered: $user_input"
fi
⚠️ Don't mix strings and integers. You won't see an error but you won't get the intended result as well.
declare -i number="abc"
echo $number # Output: 0 (not an error!)
-g
option to create global variables when used inside a shell function.Use array variables (-a)
You can create indexed arrays explicitly with option -a
:
declare -a array_var=("get" "LHB" "Pro" "Membership")
A better example that shows things in action:
declare -a fruits=("apple" "banana" "orange")
declare -a numbers
# Add elements
fruits[3]="grape"
numbers[0]=100
numbers[1]=200
echo ${fruits[@]} # Output: apple banana orange grape
echo ${#fruits[@]} # Output: 4 (array length)
⚠️ Beware of the index gap issues. In the example below, the element was added at 11th position but length of the array is still counted as 2. Basically, bash is not a high-level programming language. So, be careful of the pitfalls.
declare -a sparse_array
sparse_array[0]="first"
sparse_array[10]="eleventh"
echo ${#sparse_array[@]} # Output: 2 (not 11!)
Declare associative arrays (-A)
I hope you are familiar with the concept of associative arrays in bash. Basically, Associative arrays let you create structured data with key-value pairs, offering a more flexible way to handle data compared to indexed arrays.
declare -A user_info
user_info["name"]="Alice"
user_info["age"]=30
user_info["role"]="developer"
echo ${user_info["name"]} # Output: Alice
echo ${!user_info[@]} # Output: name age role (keys)
echo ${user_info[@]} # Output: Alice 30 developer (values)
declare -r -x -i MAX_WORKERS=4
will create a read-only, exported, integer.Create exported variables (-x)
By default, the variables you create are not available to the child
Make variables available to child processes with option -x
.
In the screenshot below, you can see that the exported variable with declare was available in the subshell while the normal variable was not.

This is useful when you have scripts with the variables that need to be available beyond the current shell. An example with pseudocode:
declare -x DATABASE_URL="postgresql://localhost/mydb"
declare -x -r CONFIG_FILE="/etc/myapp.conf" # Read-only AND exported
# Now DATABASE_URL is available to any command you run
python my_script.py # Can access DATABASE_URL
Unsetting attributes
You can also remove specific attributes from variables by using + in the option.
In the example below, I have the variable set as an integer first and then I change it to a string.
declare -i number=42
declare +i number # Remove integer attribute
number="hello" # Now this works (was previously integer-only)
Just letting you know that this option is also there if the situation demands it.
declare -p variable_name
will show specific variable attributesdeclare -p
will show all variables in the system with their attributes. Pretty huge output.When and where should you use declare?
Use declare
when you want to:
- Create constants with
-r
- Work with arrays (
-a
or-A
) - Ensure variables are integers (
-i
) - Make variables available to child processes (
-x
) - Create more readable, self-documenting code
Stick with simple assignment when:
- Creating basic string variables
- Working with temporary values
- Writing quick one-liners
I can think of some practical, real-world use cases.
Let's say you are creating a script for system monitoring (pseudocode for example):
#!/bin/bash
# System thresholds (read-only)
declare -r -i CPU_THRESHOLD=80
declare -r -i MEMORY_THRESHOLD=85
declare -r -i DISK_THRESHOLD=90
# Current values (will be updated)
declare -i current_cpu
declare -i current_memory
declare -i current_disk
# Arrays for storing historical data
declare -a cpu_history
declare -a memory_history
# Function to check system resources
check_system() {
current_cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
current_memory=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}')
# Add to history
cpu_history+=($current_cpu)
memory_history+=($current_memory)
# Alert if thresholds exceeded
if (( current_cpu > CPU_THRESHOLD )); then
echo "⚠️ CPU usage high: ${current_cpu}%"
fi
if (( current_memory > MEMORY_THRESHOLD )); then
echo "⚠️ Memory usage high: ${current_memory}%"
fi
}
Or, configuration management of your web service:
#!/bin/bash
# Application configuration
declare -r APP_NAME="MyWebApp"
declare -r APP_VERSION="2.1.0"
declare -r CONFIG_DIR="/etc/myapp"
# Runtime settings (can be modified)
declare -i PORT=8080
declare -i MAX_CONNECTIONS=100
# Export for child processes
declare -x DATABASE_URL="postgresql://localhost/myapp"
declare -x LOG_LEVEL="INFO"
echo "Starting $APP_NAME v$APP_VERSION on port $PORT"
Wrapping Up
The declare
command transforms bash from a simple scripting language into a more robust programming environment. It's not just about creating variables - it's about creating reliable, maintainable scripts that handle data properly.
That being said, there are still a few pitfalls you should avoid. I mentioned a few of them in the article but it is always good to double test your scripts.
Let me know if you have questions on the usage of declare shell built-in.
Creator of Linux Handbook and It's FOSS. An ardent Linux user who has new-found love for self-hosting, homelabs and local AI.