Shell Variables
Understanding and managing variables in Linux shell environments
Basic Syntax:
VARIABLE_NAME=valueexport VARIABLE_NAME=valueecho $VARIABLE_NAME
Description
Shell variables are fundamental components of Linux shell environments that store data values for use by the shell and programs. They can be local to the current shell session or exported as environment variables to be inherited by child processes. Understanding variables is essential for shell scripting, system configuration, and effective command-line usage.
Note: Variable names are case-sensitive and by convention are often written in uppercase for environment variables and lowercase for local variables.
Types of Variables
| Type | Scope | Description |
|---|---|---|
Local Variables |
Current shell only | Available only in the current shell session |
Environment Variables |
Current shell and children | Exported to child processes and subshells |
Special Variables |
Shell-specific | Built-in variables with special meanings |
Positional Parameters |
Script/function | Command-line arguments and function parameters |
Creating and Using Variables
Basic variable assignment:
# Create a local variable MY_VAR="Hello World" echo $MY_VAR # Output: Hello World # No spaces around the equals sign! NAME="John Doe" echo "Welcome, $NAME" # Output: Welcome, John Doe
Environment variables:
# Create and export in one step export PATH="/usr/local/bin:$PATH" # Create local, then export MY_CONFIG="/etc/myapp.conf" export MY_CONFIG # Check if variable is exported declare -p MY_CONFIG # Output: declare -x MY_CONFIG="/etc/myapp.conf"
Variable expansion:
# Basic expansion
USER_HOME="/home/$USER"
echo $USER_HOME
# Brace expansion (recommended)
USER_HOME="/home/${USER}"
echo ${USER_HOME}
# Default values
echo ${UNDEFINED_VAR:-"default value"}
# Output: default value
Common Environment Variables
| Variable | Description | Example Value |
|---|---|---|
PATH |
Executable search path | /usr/bin:/bin:/usr/local/bin |
HOME |
User's home directory | /home/username |
USER |
Current username | john |
SHELL |
Current shell | /bin/bash |
PWD |
Present working directory | /home/john/projects |
OLDPWD |
Previous working directory | /home/john |
LANG |
System language/locale | en_US.UTF-8 |
TERM |
Terminal type | xterm-256color |
Special Variables
| Variable | Description |
|---|---|
$0 |
Name of the script or shell |
$1, $2, ... |
Positional parameters (command-line arguments) |
$# |
Number of positional parameters |
$@ |
All positional parameters as separate words |
$* |
All positional parameters as single word |
$$ |
Process ID of current shell |
$? |
Exit status of last command |
$! |
Process ID of last background job |
Variable Expansion Techniques
Parameter expansion:
# Default values
echo ${VAR:-default} # Use default if VAR is unset
echo ${VAR:=default} # Set VAR to default if unset
echo ${VAR:+alternative} # Use alternative if VAR is set
# String length
NAME="John"
echo ${#NAME} # Output: 4
# Substring extraction
TEXT="Hello World"
echo ${TEXT:0:5} # Output: Hello
echo ${TEXT:6} # Output: World
Pattern matching:
FILENAME="document.txt.backup"
# Remove shortest match from end
echo ${FILENAME%.*} # Output: document.txt
# Remove longest match from end
echo ${FILENAME%%.*} # Output: document
# Remove shortest match from beginning
echo ${FILENAME#*.} # Output: txt.backup
# Remove longest match from beginning
echo ${FILENAME##*.} # Output: backup
Case modification:
TEXT="Hello World"
# Convert to uppercase
echo ${TEXT^^} # Output: HELLO WORLD
# Convert to lowercase
echo ${TEXT,,} # Output: hello world
# Capitalize first letter
echo ${TEXT^} # Output: Hello world
Working with Arrays
Array variables:
# Create an array
FRUITS=("apple" "banana" "orange")
# Access elements
echo ${FRUITS[0]} # Output: apple
echo ${FRUITS[1]} # Output: banana
# All elements
echo ${FRUITS[@]} # Output: apple banana orange
# Array length
echo ${#FRUITS[@]} # Output: 3
# Add elements
FRUITS+=("grape")
echo ${FRUITS[@]} # Output: apple banana orange grape
Variable Management Commands
Viewing variables:
# List all variables set # List environment variables only env printenv # Show specific variable echo $PATH printenv PATH # Check if variable is set declare -p VARIABLE_NAME 2>/dev/null && echo "Set" || echo "Not set"
Unsetting variables:
# Remove a variable
unset MY_VAR
# Remove from environment
unset PATH # Be careful with this!
# Check if unset
echo ${MY_VAR:-"Variable is unset"}
Practical Examples
Script with command-line arguments:
#!/bin/bash
# script.sh - Example script using variables
SCRIPT_NAME=$0
FIRST_ARG=$1
SECOND_ARG=$2
ARG_COUNT=$#
echo "Script name: $SCRIPT_NAME"
echo "First argument: ${FIRST_ARG:-'Not provided'}"
echo "Second argument: ${SECOND_ARG:-'Not provided'}"
echo "Total arguments: $ARG_COUNT"
echo "All arguments: $@"
# Usage: ./script.sh hello world
Configuration management:
#!/bin/bash
# Configuration script
# Set default values
CONFIG_DIR=${CONFIG_DIR:-"/etc/myapp"}
LOG_LEVEL=${LOG_LEVEL:-"INFO"}
DEBUG_MODE=${DEBUG_MODE:-"false"}
# Create configuration
cat > app.conf << EOF
config_dir=$CONFIG_DIR
log_level=$LOG_LEVEL
debug_mode=$DEBUG_MODE
EOF
echo "Configuration created with:"
echo "Config Dir: $CONFIG_DIR"
echo "Log Level: $LOG_LEVEL"
echo "Debug Mode: $DEBUG_MODE"
PATH manipulation:
# Add directory to PATH
export PATH="$HOME/bin:$PATH"
# Add to end of PATH
export PATH="$PATH:/opt/custom/bin"
# Remove directory from PATH
PATH=$(echo $PATH | tr ':' '\n' | grep -v '/unwanted/path' | tr '\n' ':' | sed 's/:$//')
# Check if directory is in PATH
if [[ ":$PATH:" == *":/usr/local/bin:"* ]]; then
echo "/usr/local/bin is in PATH"
fi
Variable Scoping
Local vs global variables:
#!/bin/bash
# Global variable
GLOBAL_VAR="I'm global"
function test_scope() {
# Local variable (only in function)
local LOCAL_VAR="I'm local"
# Modify global variable
GLOBAL_VAR="Modified global"
echo "Inside function:"
echo "Global: $GLOBAL_VAR"
echo "Local: $LOCAL_VAR"
}
echo "Before function: $GLOBAL_VAR"
test_scope
echo "After function: $GLOBAL_VAR"
echo "Local outside function: ${LOCAL_VAR:-'Not accessible'}"
Best Practices
- Use uppercase for environment variables, lowercase for local variables
- Always quote variable expansions:
"$VAR"instead of$VAR - Use braces for clarity:
${VAR}instead of$VAR - Provide default values for optional variables
- Use
localkeyword for function variables - Validate important variables before using them
- Use meaningful variable names
- Document environment variables in scripts
- Be careful when modifying system variables like PATH
- Use
readonlyfor constants
Common Pitfalls
- Spaces around equals sign:
VAR = value(wrong) vsVAR=value(correct) - Unquoted variables can cause word splitting and globbing
- Using
$*instead of$@in most cases - Not checking if variables are set before using them
- Overwriting important system variables accidentally
- Not using local variables in functions
- Case sensitivity issues with variable names
Advanced Techniques
Dynamic variable names:
# Create variables dynamically
for i in {1..3}; do
declare "VAR_$i=value$i"
done
# Access dynamic variables
for i in {1..3}; do
var_name="VAR_$i"
echo "${!var_name}" # Indirect expansion
done
Variable validation:
#!/bin/bash
# Validate required variables
required_vars=("DATABASE_URL" "API_KEY" "LOG_DIR")
for var in "${required_vars[@]}"; do
if [[ -z "${!var}" ]]; then
echo "Error: $var is not set"
exit 1
fi
done
echo "All required variables are set"