5.2. Variables & Expansion#
Variables are the fundamental way bash stores and manipulates data. Unlike compiled languages, bash variables are simple: they’re just named containers for strings. But that simplicity hides depth—understanding variable expansion is key to writing robust scripts.
5.2.1. Quick Reference#
Task |
Syntax |
Example |
|---|---|---|
Create variable |
|
|
Use variable |
|
|
Quote in string |
Double quotes |
|
No expansion |
Single quotes |
|
Export to children |
|
|
Unset variable |
|
|
Test if set |
|
(Chapter 6) |
Default value |
|
(Section 504) |
5.2.2. Common Mistakes#
5.2.2.1. ❌ Mistake 1: Spaces Around =#
$ x = 5
bash: x: command not found
$ x=5 # ✓ Correct
5.2.2.2. ❌ Mistake 2: Forgetting Quotes#
$ filename="My File.txt"
$ cat $filename
cat: My: No such file or directory
cat: File.txt: No such file or directory
$ cat "$filename" # ✓ Correct
My File.txt
5.2.2.3. ❌ Mistake 3: Unquoted in If Statements#
$ count="10"
$ if [ $count -gt 5 ]; then # Works but risky
echo "High"
fi
$ if [ "$count" -gt 5 ]; then # ✓ Always quote
echo "High"
fi
5.2.2.4. ❌ Mistake 4: Assuming Variables Persist#
$ (x=5) # Subshell
$ echo $x
# (empty, x was in subshell only)
$ x=5 # Direct assignment
$ echo $x
5
5.2.3. Real-World Examples#
5.2.3.1. Script with Variables#
#!/bin/bash
# Configuration variables
log_file="/var/log/app.log"
backup_dir="/backups"
max_size=1000000 # 1MB
# Process the log
if [ -f "$log_file" ]; then
size=$(stat -f%z "$log_file")
if [ $size -gt $max_size ]; then
cp "$log_file" "$backup_dir/app.log.$(date +%s)"
> "$log_file" # Clear it
echo "Log rotated"
fi
fi
5.2.3.2. Using Command Output in Variables#
# Capture command output
$ files=$(ls *.txt)
$ echo "Found files: $files"
# Use in loop
for f in $files; do
echo "Processing $f"
done
# Capture with backticks (older syntax)
$ files=`ls *.txt`
# $(command) is preferred (nests better)
5.2.3.3. Variables in Paths#
# Build a dynamic path
project_name="myapp"
version="2.1"
build_dir="/opt/${project_name}/${version}"
echo "Installing to: $build_dir"
mkdir -p "$build_dir"
5.2.4. Unset Variables#
# Unset a variable
$ x="hello"
$ unset x
$ echo $x
# (empty, variable no longer exists)
# Check if variable is set
$ if [ -z "$x" ]; then
echo "x is empty or not set"
fi
5.2.5. Variable Scope#
5.2.5.1. Function Scope#
# Global variable
count=10
# Function using global
increment_global() {
((count++))
}
increment_global
echo $count # 11
# Function with local variable
my_function() {
local temp="only in function"
global="changed here"
}
my_function
echo $global # "changed here"
echo $temp # (empty, not in scope)
More on this in Chapter 8.
5.2.6. Environment vs Local Variables#
5.2.6.1. Local Variables (Current Shell)#
$ myvar="hello"
$ echo $myvar
hello
# Exit shell, variable is lost
$ exit
5.2.6.2. Environment Variables (Exported)#
# Create and export
$ export API_KEY="secret123"
# Or set and export together
$ export APP_MODE="production"
# Now child processes inherit it
$ bash -c 'echo $API_KEY'
secret123
# Check exported variables
$ env | grep API_KEY
API_KEY=secret123
5.2.6.3. When to Export#
Variables needed by child processes: export
Variables local to script: don’t export
#!/bin/bash
# Local variable (only this script)
filename="data.txt"
# Environment variable (for subcommands)
export JAVA_HOME="/usr/local/java"
export PATH="$PATH:./bin"
# Use local variable
process_file "$filename"
# Use environment variable in subprocess
java -version # Uses $JAVA_HOME
5.2.7. Expansion: What Gets Replaced#
When bash encounters $something, it expands it. This is called variable expansion.
5.2.7.1. Types of Expansion#
# Simple variable expansion
$ name="Alice"
$ echo $name
Alice
# Parameter expansion (with braces, more explicit)
$ echo ${name}
Alice
# Needed when variable name is ambiguous
$ file="data"
$ echo ${file}txt # ✓ RIGHT: ${file}txt → datatxt
$ echo $filetxt # ✗ WRONG: looks for variable $filetxt
5.2.7.2. Expansion in Different Contexts#
# In double quotes
$ echo "Name: $name"
Name: Alice
# In single quotes (NO expansion)
$ echo 'Name: $name'
Name: $name
# Unquoted (word splitting happens)
$ echo $name
Alice
# In arithmetic
$ x=5
$ echo $((x + 1))
6
# In if statements
if [ "$count" -gt 10 ]; then
echo "Many!"
fi
5.2.8. Special Variables#
Bash provides built-in variables with special meaning:
5.2.8.1. Common Built-in Variables#
Variable |
Meaning |
Example |
|---|---|---|
|
Script name |
|
|
Arguments |
|
|
All arguments |
|
|
Number of arguments |
|
|
Last exit code |
|
|
Process ID |
|
|
Random number 0-32767 |
|
|
Home directory |
|
|
Current directory |
|
|
Executable search path |
|
|
Current username |
|
5.2.8.2. Examples#
# Current user
$ echo "Logged in as: $USER"
Logged in as: alice
# Home directory
$ echo "Home is: $HOME"
Home is: /home/alice
# Current directory
$ echo "Working in: $PWD"
Working in: /home/alice/scripts
# Random number
$ echo $RANDOM
24538
# Random between 1-10
$ echo $((RANDOM % 10 + 1))
7
5.2.9. Using Variables#
5.2.9.1. Basic Reference#
$ name="Alice"
$ echo $name
Alice
# Both work, but $var is more common
$ echo $name
$ echo ${name}
# In scripts, ${name} is safer (less ambiguous)
5.2.9.2. Variables in Strings#
Remember quoting from section 0502:
$ name="Alice"
$ greeting="Hello $name"
$ echo $greeting
Hello Alice
$ greeting='Hello $name'
$ echo $greeting
Hello $name
# Single quotes prevent expansion
5.2.9.3. Variables in Commands#
# Variable used as argument
$ filename="data.txt"
$ wc -l "$filename"
10 data.txt
# Variable in a pattern
$ pattern="error"
$ grep "$pattern" logfile.txt
# Variable as part of a filename
$ backup_dir="/backups"
$ cp datafile.txt "$backup_dir/datafile.txt.bak"
5.2.10. Creating Variables#
5.2.10.1. Basic Assignment#
# Create a variable and assign a value
$ name="Alice"
$ echo $name
Alice
# Note: NO spaces around the = sign
$ name = "Alice" # ❌ WRONG: "name" is interpreted as a command
bash: name: command not found
$ name="Alice" # ✓ RIGHT: Variable assignment
5.2.10.2. Variable Naming Rules#
# Valid variable names
$ count=5
$ _private=10
$ myVar="test"
$ MY_CONSTANT="PROD"
# Invalid (these won't work)
$ 1st="invalid" # ❌ Can't start with number
$ my-var="test" # ❌ Can't use hyphen
$ my var="test" # ❌ Can't have spaces
$ my$var="test" # ❌ Can't use special characters
5.2.10.3. Conventions#
Lowercase for local variables:
filename,countUPPERCASE for constants:
API_KEY,MAX_RETRIESUnderscore prefix for private:
_internal_varMeaningful names:
temp_filenottf