Execution flow in shell scripting relies on three fundamental mechanisms: sequential processing, conditional selection, and iterative loops. Selection logic allows scripts to make decisions based on runtime states, primarily utilizing logical operatros, conditional blocks, and match statements.
Conditional Logic in Bash
Conditional blocks evaluate expressions to determine which code path executes. There are three primary structures for handling conditions.
Single-Branch Condition Executes a block only when the expression evaluates to true.
if [[ condition ]]; then
# actions when true
fi
Double-Branch Condition Provides an alternative path when the expression is false.
if [[ condition ]]; then
# actions when true
else
# actions when false
fi
Multi-Branch Condition Checks multiple expressions sequentially. Execution stops at the first true condition.
if [[ condition1 ]]; then
# actions for condition 1
elif [[ condition2 ]]; then
# actions for condition 2
else
# default actions
fi
Example: File Type Identification The following script validates input arguments and identifies the nature of the specified path.
#!/bin/bash
target_path="${1}"
if [[ -z "${target_path}" ]]; then
echo "Error: No path provided."
exit 1
fi
if [[ ! -e "${target_path}" ]]; then
echo "Error: Path does not exist."
exit 2
fi
if [[ -f "${target_path}" ]]; then
echo "Type: Regular File"
elif [[ -d "${target_path}" ]]; then
echo "Type: Directory"
elif [[ -L "${target_path}" ]]; then
echo "Type: Symbolic Link"
elif [[ -b "${target_path}" ]]; then
echo "Type: Block Device"
elif [[ -c "${target_path}" ]]; then
echo "Type: Character Device"
elif [[ -S "${target_path}" ]]; then
echo "Type: Socket"
else
echo "Type: Unknown"
fi
Example: User Role Classification This script accepts a username and categorizes the account based on its User ID (UID).
#!/bin/bash
query_user="${1}"
if [[ -z "${query_user}" ]]; then
echo "Usage: Provide a username."
exit 1
fi
if ! id "${query_user}" &>/dev/null; then
echo "Error: User not found."
exit 2
fi
uid_value=$(id -u "${query_user}")
if [[ ${uid_value} -eq 0 ]]; then
echo "Role: Superuser"
elif [[ ${uid_value} -ge 1000 ]]; then
echo "Role: Standard Login User"
else
echo "Role: System Service Account"
fi
Example: Interactive System Monitor Users can select specific hardware information to display via a text menu.
#!/bin/bash
cat << MENU
1) disk) Display partition table
2) mem) Display memory usage
3) cpu) Display processor info
4) quit) Exit script
MENU
read -p "Select an option: " user_choice
if [[ "${user_choice}" =~ ^disk$ ]]; then
lsblk
elif [[ "${user_choice}" =~ ^mem$ ]]; then
free -h
elif [[ "${user_choice}" =~ ^cpu$ ]]; then
nproc
else
echo "Exiting."
exit 0
fi
Iterative Processes in Bash
Loops allow repeated execution of code blocks. Bash supports for, while, and until constructs. The for loop is commonly used for iterating over lists or sequences.
List Iteration The loop continues as long as there are items in the provided list.
for variable in list; do
# commands
done
Lists can be generated via explicit strings, brace expansion, command output, or glob patterns.
Example: Batch User Provisioning Checks a list of usernames and creates them if they do not already exist.
#!/bin/bash
user_list=("dev01" "dev02" "dev03")
for uname in "${user_list[@]}"; do
if id "${uname}" &>/dev/null; then
echo "Skip: ${uname} exists."
else
useradd "${uname}" && echo "Created: ${uname}"
fi
done
Example: Arithmetic Accumulation Calculates the sum of integers within a specific range.
#!/bin/bash
total_sum=0
for num in $(seq 1 100); do
(( total_sum += num ))
done
echo "Total: ${total_sum}"
Example: Directory Content Analysis Iterates through files in a specific directory to identify their types.
#!/bin/bash
search_dir="/etc"
for entry in "${search_dir}"/*; do
if [[ -f "${entry}" ]]; then
echo "File: ${entry}"
elif [[ -d "${entry}" ]]; then
echo "Dir: ${entry}"
elif [[ -L "${entry}" ]]; then
echo "Link: ${entry}"
else
echo "Other: ${entry}"
fi
done