Common loop structures in Shell scripts include for loops, while loops, and until loops.
for Loop
Basic Syntax
bashfor variable in list do commands done
Iterating Over Lists
bash# Iterate over string list for fruit in apple banana orange do echo "Fruit: $fruit" done # Iterate over number sequence for i in 1 2 3 4 5 do echo "Number: $i" done # Use seq command to generate sequence for i in $(seq 1 10) do echo "Number: $i" done # Use {start..end} syntax (Bash 3.0+) for i in {1..10} do echo "Number: $i" done # Specify step for i in {0..10..2} do echo "Number: $i" done
C-style for Loop
bash# C-style syntax for (( i=0; i<10; i++ )) do echo "Number: $i" done # Multiple variables for (( i=0, j=10; i<10; i++, j-- )) do echo "i=$i, j=$j" done
Iterating Over Files and Directories
bash# Iterate over files in current directory for file in *.txt do echo "Processing: $file" done # Iterate over command output for user in $(cut -d: -f1 /etc/passwd) do echo "User: $user" done # Recursively iterate over directories for file in $(find . -name "*.sh") do echo "Shell script: $file" done
while Loop
Basic Syntax
bashwhile condition do commands done
while Loop Examples
bash# Counter count=0 while [ $count -lt 5 ] do echo "Count: $count" count=$((count + 1)) done # Read file lines while IFS= read -r line do echo "Line: $line" done < input.txt # Read user input while true do read -p "Enter 'quit' to exit: " input if [ "$input" = "quit" ]; then break fi echo "You entered: $input" done # Wait for process to finish while ps -p $PID > /dev/null do echo "Process is running..." sleep 1 done echo "Process finished"
until Loop
Basic Syntax
bashuntil condition do commands done
until Loop Examples
bash# Wait for condition to be true count=0 until [ $count -ge 5 ] do echo "Count: $count" count=$((count + 1)) done # Wait for service to start until curl -s http://localhost:8080 > /dev/null do echo "Waiting for service..." sleep 2 done echo "Service is ready"
Loop Control Statements
break Statement
bash# Break out of loop for i in {1..10} do if [ $i -eq 5 ]; then break fi echo "Number: $i" done # Output: 1 2 3 4
continue Statement
bash# Skip current iteration for i in {1..10} do if [ $((i % 2)) -eq 0 ]; then continue fi echo "Odd number: $i" done # Output: 1 3 5 7 9
break and continue with Levels
bash# Break out of nested loops for i in {1..3} do for j in {1..3} do if [ $i -eq 2 ] && [ $j -eq 2 ]; then break 2 fi echo "i=$i, j=$j" done done
Practical Application Examples
bash#!/bin/bash # Example 1: Batch process files echo "Processing text files..." for file in *.txt do if [ -f "$file" ]; then echo "Processing: $file" # Add processing logic here cp "$file" "backup_$file" fi done # Example 2: Monitor process echo "Monitoring process..." while true do if ps aux | grep -q "[m]yprocess"; then echo "Process is running" else echo "Process stopped" break fi sleep 5 done # Example 3: Wait for multiple services services=("service1" "service2" "service3") for service in "${services[@]}" do echo "Waiting for $service..." until systemctl is-active --quiet "$service" do sleep 2 done echo "$service is ready" done # Example 4: Read configuration file echo "Reading configuration..." while IFS='=' read -r key value do # Skip comments and empty lines [[ $key =~ ^#.*$ ]] && continue [[ -z $key ]] && continue echo "Config: $key = $value" done < config.txt # Example 5: Parallel processing max_parallel=3 count=0 for task in task1 task2 task3 task4 task5 do # Start background task echo "Starting $task..." ( sleep 2 echo "$task completed" ) & count=$((count + 1)) # Control parallelism if [ $((count % max_parallel)) -eq 0 ]; then wait fi done wait echo "All tasks completed"
Loop Best Practices
- Quote variables: Prevent issues with spaces and special characters
- Set IFS for special delimiters:
IFS= read -r line - Use break and continue: Improve code readability
- Avoid infinite loops: Ensure while and until loops have exit conditions
- Use wait for background processes: Ensure all tasks complete
- Prefer C-style for loops: Clearer for number sequences
- Use array iteration:
for item in "${array[@]}"