10 Practical Bash For Loop Examples in Linux

The for loop is one of the most fundamental constructs in Bash scripting. Whether you are renaming hundreds of files, automating server backups, iterating over a list of IP addresses, or processing command outputs, mastering the for loop saves you hours of repetitive command-line work.

In this tutorial, we will explore 10 practical, real-world examples of Bash for loops in Linux, starting from basic syntax and moving to advanced automation patterns.


Basic Bash For Loop Syntax

In Bash, a standard for loop iterates through a list of items and executes a block of commands for each element:

for item in item1 item2 item3 ...
do
    # Commands to execute for each item
    echo "$item"
done

You can also write it as a concise one-liner by separating statements with semicolons:

for item in item1 item2 item3; do echo "$item"; done

Let’s dive into 10 practical examples.


1. Loop Through a List of Static Strings

The simplest way to use a for loop is iterating over hardcoded items separated by spaces.

#!/usr/bin/env bash

for fruit in Apple Banana Cherry Orange
do
    echo "Fruit: $fruit"
done

Output:

Fruit: Apple
Fruit: Banana
Fruit: Cherry
Fruit: Orange

2. Loop Through a Range of Numbers (Brace Expansion)

Using Bash brace expansion {start..end}, you can generate a sequence of numbers without writing external utilities like seq.

#!/usr/bin/env bash

for i in {1..5}
do
    echo "Iteration number: $i"
done

Output:

Iteration number: 1
Iteration number: 2
Iteration number: 3
Iteration number: 4
Iteration number: 5

3. Loop with Step Increments

You can specify a step interval using {start..end..step}:

See also: Mastering the Linux Command Line — Your Complete Free Training Guide

#!/usr/bin/env bash

# Count from 0 to 20 by 5s
for num in {0..20..5}
do
    echo "Value: $num"
done

Output:

Value: 0
Value: 5
Value: 10
Value: 15
Value: 20

4. C-Style (Three-Expression) For Loop

Bash supports the classic C-style for (( initialization; condition; increment )) syntax, ideal for arithmetic-heavy counters.

#!/usr/bin/env bash

for (( i=1; i<=5; i++ ))
do
    echo "Counter: $i"
done

Output:

Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5

5. Iterate Over Files in a Directory (Globbing)

You can iterate through files using wildcards (glob patterns). This pattern is widely used in batch file processing and backups.

#!/usr/bin/env bash

for file in /var/log/*.log
do
    if [ -f "$file" ]; then
        echo "Found log file: $file"
    fi
done

Sample Output:

Found log file: /var/log/alternatives.log
Found log file: /var/log/dpkg.log
Found log file: /var/log/auth.log

Tip: Always quote variable references (e.g., "$file") to handle filenames that contain whitespace.


6. Batch Rename Files with a For Loop

Combining a for loop with parameter expansion makes bulk-renaming operations quick and straightforward:

#!/usr/bin/env bash

# Rename all .txt files to .bak
for f in *.txt
do
    [ -e "$f" ] || continue
    mv "$f" "${f%.txt}.bak"
    echo "Renamed: $f -> ${f%.txt}.bak"
done

Sample Output:

Renamed: report1.txt -> report1.bak
Renamed: report2.txt -> report2.bak
Renamed: summary.txt -> summary.bak

7. Iterate Over Command Output (Command Substitution)

Using $(command), you can loop over the lines or words generated by an external Linux command.

#!/usr/bin/env bash

for user in $(cut -d: -f1 /etc/passwd | head -n 4)
do
    echo "System user: $user"
done

Sample Output:

System user: root
System user: daemon
System user: bin
System user: sys

8. Iterate Over Array Elements

Bash arrays paired with for loops allow robust handling of multi-element data structures:

#!/usr/bin/env bash

servers=("web01.example.com" "web02.example.com" "db01.example.com")

for server in "${servers[@]}"
do
    echo "Checking host status: $server"
done

Output:

Checking host status: web01.example.com
Checking host status: web02.example.com
Checking host status: db01.example.com

9. Ping Multiple IP Addresses / Hosts

A standard DevOps task: health-checking a subnet or list of targets.

#!/usr/bin/env bash

for ip in 192.168.1.{1..3}
do
    if ping -c 1 -W 1 "$ip" > /dev/null 2>&1; then
        echo "[UP]   $ip is reachable"
    else
        echo "[DOWN] $ip is unreachable"
    fi
done

Sample Output:

[UP]   192.168.1.1 is reachable
[UP]   192.168.1.2 is reachable
[DOWN] 192.168.1.3 is unreachable

10. Loop Control: Using break and continue

Use break to exit the loop early when a condition is met, and continue to skip the remainder of the current iteration.

#!/usr/bin/env bash

for num in {1..7}
do
    # Skip number 3
    if [ "$num" -eq 3 ]; then
        echo "Skipping $num..."
        continue
    fi

    # Terminate loop when reaching 6
    if [ "$num" -eq 6 ]; then
        echo "Found $num, terminating loop."
        break
    fi

    echo "Processing number: $num"
done

Output:

Processing number: 1
Processing number: 2
Skipping 3...
Processing number: 4
Processing number: 5
Found 6, terminating loop.

Summary Cheat Sheet

Loop PatternExample SyntaxBest Use Case
Static Listfor x in a b c; do ...; doneFixed set of values/arguments
Number Rangefor i in {1..10}; do ...; doneSequential loops & counters
Step Intervalfor i in {0..100..10}; do ...; doneIncremental stepping & sampling
C-Style Loopfor ((i=0; i<n; i++)); do ...; doneArithmetic indexing & conditions
Glob / Filesfor f in *.log; do ...; doneFile system batch operations
Command Outputfor x in $(cat list.txt); do ...; doneProcessing dynamic tool output
Arrayfor el in "${arr[@]}"; do ...; doneStructured arrays & safety with spaces

Best Practices for Bash Loops

  1. Always quote variables ("$file", "$item") to prevent word splitting issues with filenames containing spaces.
  2. Handle empty glob matches with [ -e "$f" ] || continue to avoid processing the literal wildcard string (e.g., *.txt) when no files match.
  3. Prefer read loops (while IFS= read -r line) over for item in $(cat file.txt) when processing files line by line, as for splits by any whitespace.
Avatar photo
David Cao

David is a Cloud & DevOps Enthusiast. He has years of experience as a Linux engineer. He had working experience in AMD, EMC. He likes Linux, Python, bash, and more. He is a technical blogger and a Software Engineer. He enjoys sharing his learning and contributing to open-source.

Articles: 275

Leave a Reply

Your email address will not be published. Required fields are marked *