Kahibaro
Discord Login Register

Loops

Why Loops Matter in Shell Scripts

Loops let your script repeat actions without copying the same commands over and over. Instead of manually writing a command 10 times, you write it once and tell the shell to repeat it.

In shell scripting, the most common loops are:

bash also supports select loops (for menus), which you’ll see briefly at the end.

You already know how to run commands in a script and use variables/conditionals from previous sections; here you’ll see how to repeat blocks of commands.


`for` Loops

for loops iterate over a list of values. For each value, the loop body (the commands inside) runs once.

Basic `for` Loop Over a List

General form:

for var in item1 item2 item3; do
    commands using "$var"
done

Example:

#!/bin/bash
for fruit in apple banana cherry; do
    echo "I like $fruit"
done

Output:

I like apple
I like banana
I like cherry

Key points:

`for` Loop Over Command-Line Arguments (`$@`)

$@ represents all arguments given to the script.

#!/bin/bash
echo "You passed $# arguments."
for arg in "$@"; do
    echo "Argument: $arg"
done

If you run:

./myscript.sh one "two words" three

You get:

You passed 3 arguments.
Argument: one
Argument: two words
Argument: three

Notice the quotes: "$@" preserves spaces in each argument as a single item.

`for` Loop Over Files (Globbing)

You often loop over files matching a pattern using wildcards (covered in the wildcards chapter):

#!/bin/bash
for file in *.txt; do
    echo "Processing $file"
done

Handling “no matches” cases

If there are no .txt files, many shells (including bash by default) will keep .txt as the literal string ".txt".

A simple check:

for file in *.txt; do
    [ -e "$file" ] || { echo "No .txt files found"; break; }
    echo "Processing $file"
done

[ -e "$file" ] checks whether the file exists; if not, we print a message and break (stop the loop).

C-Style `for` Loop (Numeric Loops)

bash supports a C-like syntax for numeric loops:

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

Breakdown:

You can change the step:

for (( i=0; i<=10; i+=2 )); do
    echo "Even number: $i"
done

This is very convenient for fixed numeric ranges.

Using `seq` for Ranges (Portable Style)

On many systems, seq is available and works in more shells than C-style loops:

for i in $(seq 1 5); do
    echo "Number: $i"
done

With step:

for i in $(seq 0 2 10); do
    echo "Step 2: $i"
done

Be cautious: $(...) splits on whitespace, so it’s best for simple numeric lists, not arbitrary strings with spaces.


`while` Loops

while loops run as long as a condition (a command) returns success (exit status 0). You’ll combine them with tests and commands you already know.

General form:

while condition_command; do
    commands
done

The shell runs condition_command; if it succeeds, it runs the body and then tests the condition again.

Basic Counter with `while`

Example:

#!/bin/bash
count=1
while [ "$count" -le 5 ]; do
    echo "Count is $count"
    count=$(( count + 1 ))
done

Key points:

`while` Loop Reading User Input

while is often used for reading input repeatedly.

#!/bin/bash
while true; do
    read -p "Enter a word (or 'quit' to exit): " word
    [ "$word" = "quit" ] && break
    echo "You typed: $word"
done
echo "Goodbye!"

Notes:

`while` Loop Reading from a File

Common pattern: process a file line by line.

#!/bin/bash
file="names.txt"
while IFS= read -r line; do
    echo "Name: $line"
done < "$file"

Breakdown:

`until` Loops

until is like while, but runs until the condition becomes true (i.e., it loops while the condition is false).

General form:

until condition_command; do
    commands
done

That means:

Example:

#!/bin/bash
count=1
until [ "$count" -gt 5 ]; do
    echo "Count is $count"
    count=$(( count + 1 ))
done

This produces the same output as the earlier while example, but the logic is reversed.

until can be handy when you think in terms of “keep going until X happens”, for example:

until ping -c 1 example.com >/dev/null 2>&1; do
    echo "Waiting for example.com to respond..."
    sleep 2
done
echo "example.com is reachable!"

This loop keeps running until ping succeeds.


Controlling Loop Flow: `break` and `continue`

Inside any loop (for, while, or until), you can change control flow:

Using `break`

Stop the loop when a condition is met:

#!/bin/bash
for num in 1 2 3 4 5; do
    if [ "$num" -eq 3 ]; then
        echo "Stopping at $num"
        break
    fi
    echo "Number: $num"
done
echo "Loop finished."

Output:

Number: 1
Number: 2
Stopping at 3
Loop finished.

Using `continue`

Skip just the current iteration:

#!/bin/bash
for num in 1 2 3 4 5; do
    if [ "$num" -eq 3 ]; then
        echo "Skipping $num"
        continue
    fi
    echo "Number: $num"
done

Output:

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

Nested Loops

You can place loops inside loops. Be careful with indentation so it stays readable.

Example: simple “table” of pairs:

#!/bin/bash
for i in 1 2 3; do
    for j in a b c; do
        echo "i=$i, j=$j"
    done
done

Output:

i=1, j=a
i=1, j=b
i=1, j=c
i=2, j=a
...

You can also use break and continue with an optional numeric argument in bash to break out of multiple levels (more advanced usage), but for now, try to keep nesting shallow.


`select` Loops (Simple Menus in Bash)

select (a bash feature) makes simple numbered menus:

#!/bin/bash
PS3="Choose a fruit (or Ctrl+C to quit): "
select fruit in apple banana cherry; do
    echo "You chose: $fruit"
done

When you run this, you see:

1) apple
2) banana
3) cherry
Choose a fruit (or Ctrl+C to quit):

You can add conditions to exit the loop:

#!/bin/bash
PS3="Choose an option: "
select choice in list date quit; do
    case "$choice" in
        list)
            ls
            ;;
        date)
            date
            ;;
        quit)
            echo "Goodbye!"
            break
            ;;
        *)
            echo "Invalid choice."
            ;;
    esac
done

This combines select with case (covered in conditionals).


Common Loop Pitfalls and Tips

    command | while IFS= read -r line; do
        ...
    done

Practice Ideas

Try writing small scripts using each loop type:

  1. for:
    • Print “Hello” 10 times using a C-style for.
    • Loop over all .log files and show their sizes.
  2. while:
    • Ask the user for numbers until they enter 0, then print the sum.
    • Read a file line by line and number each line.
  3. until:
    • Keep asking for a password until the user types a specific word.
    • Wait until a particular file exists, then print a message.
  4. select (in bash):
    • Create a simple menu to run common commands (ls, pwd, date, exit).

These exercises will make loops feel natural and prepare you for more complex scripting tasks.

Views: 21

Comments

Please login to add a comment.

Don't have an account? Register now!