Skip to content

11. Bash Loops

Overview

Bash loops are used to execute a block of commands repeatedly. They are useful for automating repetitive tasks, processing files, iterating over lists, and executing commands until a specific condition is met.

Bash provides three commonly used loop types:

  • for — Iterates over a list of items.

  • while — Repeats commands while a condition is true.

  • until — Repeats commands until a condition becomes true.


Bash for Loop

A for loop is used to iterate over a list of values. It executes the commands inside the loop once for each item.

Syntax

for variable in list; do
    commands
done

Example: List Files and Directories

The following script iterates over the entries inside the /var/ directory and prints each entry.

#!/bin/bash

# Iterate over entries in /var/
for item in /var/*; do
    echo "$item"
done

Explanation

  • for item in /var/* — Assigns each entry in /var/ to the variable item.

  • do — Marks the beginning of the loop body.

  • echo "$item" — Displays the current entry.

  • done — Marks the end of the loop.

The * wildcard expands to the entries in the directory. Unlike using ls, this approach handles filenames containing spaces more reliably.

Output

/var/backups
/var/cache
/var/crash
/var/lib
/var/local
/var/log
/var/tmp

The exact output depends on the contents of the /var/ directory.

Running a for Loop Directly

A for loop can also be executed directly in the terminal without creating a script.

for item in /var/*; do echo "$item"; done

Example: Iterate Over Numbers

#!/bin/bash

for number in 1 2 3 4 5; do
    echo "Number: $number"
done

Output

Number: 1
Number: 2
Number: 3
Number: 4
Number: 5

Bash while Loop

A while loop repeatedly executes commands as long as a condition is true.

Syntax

while condition; do
    commands
done

Example: Countdown

The following script starts with a counter of 6 and decreases it by one during each iteration.

#!/bin/bash

COUNT=6

# Continue while COUNT is greater than zero
while [ "$COUNT" -gt 0 ]; do
    echo "Value of count is: $COUNT"
    ((COUNT--))
done

Explanation

  • COUNT=6 — Initializes the counter.

  • [ "$COUNT" -gt 0 ] — Checks whether COUNT is greater than zero.

  • echo — Displays the current counter value.

  • ((COUNT--)) — Decreases the counter by one.

  • done — Ends the loop.

The loop stops when COUNT becomes 0, because the condition is no longer true.

Output

Value of count is: 6
Value of count is: 5
Value of count is: 4
Value of count is: 3
Value of count is: 2
Value of count is: 1

Example: Read User Input

A while loop can be used to repeatedly ask the user for input.

#!/bin/bash

while true; do
    read -rp "Enter a command (exit to quit): " command

    if [[ "$command" == "exit" ]]; then
        break
    fi

    echo "You entered: $command"
done

Explanation

  • while true — Creates a loop that continues indefinitely.

  • read -rp — Reads input from the user.

  • [[ "$command" == "exit" ]] — Checks whether the user entered exit.

  • break — Terminates the loop.

  • Otherwise, the entered text is displayed.


Bash until Loop

An until loop repeatedly executes commands as long as a condition is false. It stops when the condition becomes true.

Syntax

until condition; do
    commands
done

Example: Count from Zero to Five

#!/bin/bash

COUNT=0

# Continue until COUNT becomes greater than 5
until [ "$COUNT" -gt 5 ]; do
    echo "Value of count is: $COUNT"
    ((COUNT++))
done

Explanation

  • COUNT=0 — Initializes the counter.

  • [ "$COUNT" -gt 5 ] — Checks whether the counter is greater than five.

  • until — Runs the loop while this condition is false.

  • ((COUNT++)) — Increases the counter by one.

  • The loop stops when COUNT becomes 6.

Output

Value of count is: 0
Value of count is: 1
Value of count is: 2
Value of count is: 3
Value of count is: 4
Value of count is: 5

Difference Between while and until

Loop Continues when Stops when
while Condition is true Condition becomes false
until Condition is false Condition becomes true

Both loops can perform the same task, but they express the stopping condition differently.


Controlling a Bash Loop with Input

A loop can read data from standard input using the read command. This is useful when processing the output of another command, such as find.

The following example searches for files in the current directory and renames files containing spaces by replacing those spaces with underscores.

Example: Rename Files Containing Spaces

#!/bin/bash

# Directory to search
DIR="."

# Find regular files and process them one at a time
find "$DIR" -type f -print0 |
while IFS= read -r -d '' file; do

    # Check whether the filename contains a space
    if [[ "$file" == *" "* ]]; then

        # Create a new filename with spaces replaced by underscores
        new_file="${file// /_}"

        # Rename the file
        mv -- "$file" "$new_file"

        echo "Renamed: $file -> $new_file"
    fi

done

Explanation

  • DIR="." — Sets the current directory as the search location.

  • find "$DIR" -type f — Searches for regular files.

  • -print0 — Separates filenames with a null character, allowing filenames containing spaces, tabs, and newlines to be handled safely.

  • IFS= read -r -d '' file — Reads one complete filename from standard input without removing backslashes or splitting on whitespace.

  • [[ "$file" == *" "* ]] — Checks whether the filename contains a space.

  • ${file// /_} — Replaces every space in the filename with an underscore.

  • mv -- "$file" "$new_file" — Renames the file.

  • done — Ends the loop.

Example Directory Before Renaming

./report one.txt
./network notes.txt
./script.sh
./backup file.tar

Example Output

Renamed: ./report one.txt -> ./report_one.txt
Renamed: ./network notes.txt -> ./network_notes.txt
Renamed: ./backup file.tar -> ./backup_file.tar

Example Directory After Renaming

./report_one.txt
./network_notes.txt
./script.sh
./backup_file.tar

Important: Renaming files changes their names on disk. Test the script in a temporary directory before using it on important files.


Loop Control Statements

Bash provides statements that control how a loop executes.

break

The break statement immediately terminates the current loop.

#!/bin/bash

for number in 1 2 3 4 5; do
    if [ "$number" -eq 4 ]; then
        break
    fi

    echo "$number"
done

Output:

1
2
3

continue

The continue statement skips the remaining commands in the current iteration and proceeds to the next iteration.

#!/bin/bash

for number in 1 2 3 4 5; do
    if [ "$number" -eq 3 ]; then
        continue
    fi

    echo "$number"
done

Output:

1
2
4
5

Useful Bash Loop Operators

Operator Meaning
-gt Greater than
-lt Less than
-eq Equal to
-ne Not equal to
-ge Greater than or equal to
-le Less than or equal to
((COUNT++)) Increase the counter by one
((COUNT--)) Decrease the counter by one
break Exit the loop
continue Skip to the next iteration

Best Practices

  • Quote variables when working with filenames, such as "$file".

  • Prefer find -print0 with read -d '' when processing arbitrary filenames.

  • Avoid using for file in $(ls ...) because it can break on spaces, tabs, and newlines in filenames.

  • Ensure that loop conditions eventually change when using while or until, unless an intentional infinite loop is being used.

  • Use ((counter++)) and ((counter--)) for arithmetic operations in Bash.

  • Test file-manipulation scripts in a safe directory before applying them to important data.


Conclusion

Bash loops are essential for automation and scripting. The for loop is useful for iterating over lists and files, the while loop runs commands while a condition remains true, and the until loop continues until a condition becomes true. Combining loops with commands such as find, read, and conditional statements allows Bash scripts to process files, handle user input, and automate repetitive tasks efficiently.