How to Loop Through Array in Bash
Quick Answer: Loop Through Array Elements
Use for item in "${array[@]}"; do ... done to iterate through each element. This is the simplest method and works for most cases. Always quote the array as "${array[@]}" to preserve spaces in elements.
Quick Comparison: Array Looping Methods
| Method | Syntax | Best For | Speed |
|---|---|---|---|
| For-in with elements | for item in "${array[@]}" | Most cases, simple iteration | Fastest |
| For-in with index | for i in "${!array[@]}" | Need index position | Very fast |
| C-style for loop | for ((i=0; i<${#array[@]}; i++)) | Precise control, reverse | Fast |
| While loop counter | while [[ $i -lt ... ]] | Complex conditions | Medium |
Bottom line: Use for item in "${array[@]}" by default. Use indexed loops only when you need the index or position.
Loop through array elements in Bash efficiently. Arrays are fundamental data structures, and understanding different looping techniques is essential for processing collections of data.
Method 1: For Loop with Elements (The Go-To Approach)
The most straightforward method iterates through each element directly without needing indices. This is your default choice for most array iterations.
When to Use Element Loop
- Processing each item in a collection
- Building lists or transforming elements
- Simple iteration without position tracking
- Most readable and fastest approach
array=(apple banana orange)
for item in "${array[@]}"; do
echo "Item: $item"
done
# Output:
# Item: apple
# Item: banana
# Item: orange
Example with different data:
colors=("red" "green" "blue" "yellow")
for color in "${colors[@]}"; do
echo "Color: $color"
done
Method 2: For Loop with Index (When You Need Position)
Access both index and value using !array[@] for indices. Use this when you need to know the position of each element.
When to Use Index Loop
- Display numbered lists (1st, 2nd, 3rd)
- Track position in array for insertion/deletion
- Replace values at specific indices
- Multi-array synchronization
array=(apple banana orange)
for i in "${!array[@]}"; do
echo "[$i] = ${array[$i]}"
done
# Output:
# [0] = apple
# [1] = banana
# [2] = orange
Example with numbered list:
items=("first" "second" "third")
for i in "${!items[@]}"; do
index=$((i + 1)) # 1-based indexing
echo "$index. ${items[$i]}"
done
# Output:
# 1. first
# 2. second
# 3. third
Method 3: While Loop with Counter (For Complex Conditions)
Use a counter variable to iterate through array indices. This method works well when you need complex conditional logic.
When to Use While Loop
- Complex loop conditions beyond simple iteration
- Breaking/continuing based on element content
- Dynamic loop modifications
- Conditional element processing
array=(1 2 3 4 5)
i=0
while [[ $i -lt ${#array[@]} ]]; do
echo "Element $i: ${array[$i]}"
((i++))
done
# Output:
# Element 0: 1
# Element 1: 2
# ...
Method 4: C-Style For Loop (For Precise Control)
Bash supports C-style for loops when you need precise control over iteration—including reverse iteration or custom step sizes.
When to Use C-Style Loop
- Reverse iteration through array
- Skipping elements (step > 1)
- Precise control over loop mechanics
- Processing every Nth element
array=(a b c d)
for ((i=0; i<${#array[@]}; i++)); do
echo "[$i] = ${array[$i]}"
done
# Reverse iteration
for ((i=${#array[@]}-1; i>=0; i--)); do
echo "Reverse [$i] = ${array[$i]}"
done
Example:
$ array=(a b c d)
$ for ((i=0; i<${#array[@]}; i++)); do echo ${array[$i]}; done
a
b
c
d
Method 5: Until Loop (Opposite of While)
Loop until a condition becomes true. This is less common but useful when your stopping condition is naturally expressed as “until X happens.”
When to Use Until Loop
- Waiting for array index to reach boundary
- Processing until specific element found
- Cleaner logic when condition is naturally inverted
array=(10 20 30 40 50)
i=0
until [[ $i -ge ${#array[@]} ]]; do
echo "${array[$i]}"
((i++))
done
Practical Examples
Example 1: Sum Array Elements
#!/bin/bash
numbers=(10 20 30 40)
sum=0
for num in "${numbers[@]}"; do
((sum += num))
done
echo "Total: $sum" # Output: Total: 100
Example 2: Find Maximum Value
#!/bin/bash
numbers=(45 23 89 12 56 34)
max=${numbers[0]}
for num in "${numbers[@]}"; do
if [ "$num" -gt "$max" ]; then
max=$num
fi
done
echo "Maximum: $max" # Output: Maximum: 89
Example 3: Filter Array Elements
#!/bin/bash
# Filter array: keep only even numbers
numbers=(1 2 3 4 5 6 7 8 9 10)
evens=()
for num in "${numbers[@]}"; do
if [ $((num % 2)) -eq 0 ]; then
evens+=("$num")
fi
done
echo "Even numbers: ${evens[@]}" # Output: 2 4 6 8 10
Example 4: Process Array with Index
#!/bin/bash
# Process array preserving indices
files=("config.txt" "data.json" "script.sh" "readme.md")
for i in "${!files[@]}"; do
file=${files[$i]}
size=$(stat -c%s "$file" 2>/dev/null || echo "0")
echo "[$i] $file ($size bytes)"
done
Output:
[0] config.txt (1024 bytes)
[1] data.json (2048 bytes)
[2] script.sh (512 bytes)
[3] readme.md (1536 bytes)
Example 5: Associative Array Loops
#!/bin/bash
# Create associative array
declare -A config=(
[host]="localhost"
[port]="8080"
[debug]="true"
[timeout]="30"
)
echo "Configuration:"
for key in "${!config[@]}"; do
echo " $key = ${config[$key]}"
done
Output:
Configuration:
host = localhost
port = 8080
debug = true
timeout = 30
Example 6: Nested Array Processing
#!/bin/bash
# Process array of arrays (simulated)
declare -a data=(
"John:30:Engineer"
"Jane:25:Manager"
"Bob:35:Developer"
)
for record in "${data[@]}"; do
IFS=':' read -r name age role <<< "$record"
printf "%-10s %-3s %s\n" "$name" "$age" "$role"
done
Output:
John 30 Engineer
Jane 25 Manager
Bob 35 Developer
Example 7: Array Transformation
#!/bin/bash
# Transform array elements
words=("hello" "world" "bash" "script")
uppercase_words=()
for word in "${words[@]}"; do
uppercase_words+=("${word^^}") # Convert to uppercase
done
echo "Original: ${words[@]}"
echo "Uppercase: ${uppercase_words[@]}"
Output:
Original: hello world bash script
Uppercase: HELLO WORLD BASH SCRIPT
Advanced Techniques
Reverse Array
#!/bin/bash
array=(1 2 3 4 5)
reversed=()
for ((i=${#array[@]}-1; i>=0; i--)); do
reversed+=("${array[$i]}")
done
echo "Original: ${array[@]}"
echo "Reversed: ${reversed[@]}"
Array Slicing
#!/bin/bash
array=(a b c d e f g h)
# Get elements from index 2 to 5
slice=("${array[@]:2:4}")
echo "Slice [2:5]: ${slice[@]}" # Output: c d e f
Deduplicate Array
#!/bin/bash
array=(apple banana apple cherry banana date)
unique=()
for item in "${array[@]}"; do
[[ ! " ${unique[@]} " =~ " ${item} " ]] && unique+=("$item")
done
echo "Unique: ${unique[@]}"
Performance Comparison
For looping through arrays:
| Method | Speed | Use Case |
|---|---|---|
for item in "${array[@]}" | Fastest | Simple iteration |
for i in "${!array[@]}" | Very Fast | Need indices |
for ((i=0; i<...)) | Fast | Precise control |
while loop | Medium | Complex conditions |
Best choice: Use for item in "${array[@]}" for most cases.
Important Considerations
Always Quote Array Variables
# Correct: prevents word-splitting
for item in "${array[@]}"; do
echo "$item"
done
# Wrong: word-splitting issues
for item in ${array[@]}; do
echo "$item" # Breaks if items have spaces
done
Array Length
# Get array length
${#array[@]} # Number of elements
${#array[*]} # Alternative syntax
# Example
array=(a b c d)
echo ${#array[@]} # Output: 4
Empty Arrays
empty_array=()
# Check if empty
if [ ${#empty_array[@]} -eq 0 ]; then
echo "Array is empty"
fi
# Loop through (safely handles empty)
for item in "${empty_array[@]}"; do
echo "$item" # Won't execute if empty
done
Multi-Word Elements
# Array with spaces in elements
array=("apple pie" "banana split" "cherry tart")
# Must use quotes to preserve
for item in "${array[@]}"; do
echo "Item: $item"
done
# Output:
# Item: apple pie
# Item: banana split
# Item: cherry tart
Quick Reference
Array looping syntax patterns:
# Create array
array=(a b c d)
array[4]=e
# Basic loop
for item in "${array[@]}"; do
echo "$item"
done
# Loop with index
for i in "${!array[@]}"; do
echo "$i: ${array[$i]}"
done
# C-style loop
for ((i=0; i<${#array[@]}; i++)); do
echo "${array[$i]}"
done
# Get length
${#array[@]}
# Associative array
declare -A assoc=([key1]="value1" [key2]="value2")
for key in "${!assoc[@]}"; do
echo "$key = ${assoc[$key]}"
done
Summary
Master array loops by remembering: use "${array[@]}" for element iteration (most common), use "${!array[@]}" when you need indices, and use C-style loops for reverse or custom iteration. Always quote your array variable to preserve spaces in elements. Test your loops with arrays containing spaces or special characters to ensure robustness. Array iteration is one of the most fundamental Bash patterns—getting it right pays dividends across all your scripts.
Recommended Pattern
#!/bin/bash
# Simple array loop (default choice)
array=("item1" "item2" "item3")
for item in "${array[@]}"; do
echo "Processing: $item"
done
# With index when needed
for i in "${!array[@]}"; do
echo "[$i] = ${array[$i]}"
done
# C-style for precise control or reverse iteration
for ((i=0; i<${#array[@]}; i++)); do
process "${array[$i]}"
done