Skip to main content

How to Loop Through Array in Bash

1 min read
bash arrays loops iteration

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

MethodSyntaxBest ForSpeed
For-in with elementsfor item in "${array[@]}"Most cases, simple iterationFastest
For-in with indexfor i in "${!array[@]}"Need index positionVery fast
C-style for loopfor ((i=0; i<${#array[@]}; i++))Precise control, reverseFast
While loop counterwhile [[ $i -lt ... ]]Complex conditionsMedium

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:

MethodSpeedUse Case
for item in "${array[@]}"FastestSimple iteration
for i in "${!array[@]}"Very FastNeed indices
for ((i=0; i<...))FastPrecise control
while loopMediumComplex 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.

#!/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