Linux CLI 62 🐧 loops in shell scripts
#!/bin/bash
# Initialize a counter variable
count=1
# While count is less than or equal to 5, print the current value and increment it
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
count=1
# While count is less than or equal to 5, print the current value and increment it
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
# Initialize a counter variable
count=1
# While count is less than or equal to 5, print the current value and increment it
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
Loops are how a script repeats work. Instead of writing the same command ten times, you write it once and let the loop run it ten times. Bash gives you two main conditional loops — while and until — plus for for iterating over lists. This chapter covers while and until; for comes next.
Key point: A while loop runs as long as its condition is true. An until loop runs until its condition becomes true. They’re mirror images — the same logic, opposite framing. Both check the condition before each iteration, so it’s possible for the body to never run.
a – while loop in shell scripts
A while loop executes its block of commands as long as the given condition remains true.
Syntax:
while [ condition ]; do
# Commands to execute
done
How it works:
[ condition ]is evaluated before each iteration.- If true, the commands inside the loop run.
- Once the commands finish, the condition is re-evaluated.
- This continues until the condition becomes false.
Basic example — count to 5:
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Count is 3 ]
[ Count is 4 ]
[ Count is 5 ]
Let’s break it down:
count=1→ initializewhile [ $count -le 5 ]→ loop whilecountis less than or equal to 5echo "Count is $count"→ print the current valuecount=$((count + 1))→ incrementdone→ end of loop
⚠️ Warning: If you forget to increment, the loop runs forever — an infinite loop. Always make sure something inside the loop moves the condition toward false.
The break command — exit the loop early:
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Breaking loop at count 3. ]
break immediately exits the loop, even though the condition was still true. Control passes to the first command after done.
The continue command — skip to the next iteration:
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Skipping count 3. ]
[ Count is 4 ]
[ Count is 5 ]
continue skips the rest of the current iteration and jumps back to the condition check. In this example, when count is 3, the loop prints “Skipping”, increments, and moves on — the echo "Count is $count" is never reached for that iteration.
Note: In a
whileloop, if you usecontinue, make sure you increment before continuing — otherwise you’ll be stuck on the same value forever.
The classic infinite loop:
while true; do
echo "Running..."
sleep 1
done
true is a command that always returns 0 (success). The loop runs until you kill it with Ctrl+C or hit a break.
Reading input with a while loop:
while read -r line; do
echo "Line: $line"
done < file.txt
This reads a file line by line. The loop ends when read returns non-zero — which it does at end-of-file.
A menu with a while loop:
while true; do
echo "1) Date"
echo "2) Uptime"
echo "3) Quit"
read -p "Choice: " choice
case "$choice" in
1) date ;;
2) uptime ;;
3) break ;;
*) echo "Invalid" ;;
esac
done
The loop runs forever until the user chooses “Quit”, which triggers break.
More while loop examples:
# Countdown
count=5
while [ $count -gt 0 ]; do
echo "$count"
count=$((count - 1))
done
echo "Liftoff!"
# Sum numbers from 1 to 10
sum=0
n=1
while [ $n -le 10 ]; do
sum=$((sum + n))
n=$((n + 1))
done
echo "Sum: $sum"
[ Sum: 55 ]
# Retry until success
attempts=0
until curl -s https://example.com > /dev/null; do
attempts=$((attempts + 1))
if [ $attempts -ge 5 ]; then
echo "Giving up after 5 attempts"
break
fi
sleep 1
done
Nested while loops:
i=1
while [ $i -le 3 ]; do
j=1
while [ $j -le 3 ]; do
echo "$i x $j = $((i * j))"
j=$((j + 1))
done
i=$((i + 1))
done
[ 1 x 1 = 1 ]
[ 1 x 2 = 2 ]
[ 1 x 3 = 3 ]
[ 2 x 1 = 2 ]
[ 2 x 2 = 4 ]
[ 2 x 3 = 6 ]
[ 3 x 1 = 3 ]
[ 3 x 2 = 6 ]
[ 3 x 3 = 9 ]
break with a level (bash 4+):
while true; do
while true; do
break 2 # breaks out of BOTH loops
done
done
break 2 exits two levels of loops. continue 2 similarly continues the outer loop.
b – until loop in shell scripts
An until loop is a control flow statement that repeatedly executes a block of code as long as a specified condition evaluates to false. Once the condition becomes true, the loop terminates.
Syntax:
until [ condition ]; do
# Commands to execute
done
[ condition ] is the condition that must become true for the loop to exit.
Example — interactive until loop:
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
[ Please enter your name (or type 'exit' to quit): ]
Alice
[ Hello, Alice! ]
[ Please enter your name (or type 'exit' to quit): ]
Bob
[ Hello, Bob! ]
[ Please enter your name (or type 'exit' to quit): ]
(empty)
[ You did not provide any input. Please try again. ]
[ Please enter your name (or type 'exit' to quit): ]
exit
# loop ends
The loop continues until the user types exit. until reads naturally here: “until the user types exit, keep asking.”
Simple countdown with until:
count=5
until [ $count -eq 0 ]; do
echo "$count"
count=$((count - 1))
done
echo "Done!"
[ 5 ]
[ 4 ]
[ 3 ]
[ 2 ]
[ 1 ]
[ Done! ]
Wait for a file to appear:
until [ -f /tmp/ready ]; do
echo "Waiting for /tmp/ready..."
sleep 1
done
echo "File appeared!"
Wait for a service to be reachable:
until curl -s http://localhost:8080/health > /dev/null; do
echo "Service not ready, retrying..."
sleep 2
done
echo "Service is up!"
while vs until:
| Aspect | while | until |
|---|---|---|
| Runs while | Condition is true | Condition is false |
| Stops when | Condition becomes false | Condition becomes true |
| Typical use | Known iteration count | Waiting for an event |
| Reads naturally as | “While X, do Y” | “Until X, do Y” |
The same loop written both ways:
# while version
count=1
while [ $count -le 5 ]; do
echo "$count"
count=$((count + 1))
done
# until version — same output
count=1
until [ $count -gt 5 ]; do
echo "$count"
count=$((count + 1))
done
Both print 1 through 5. The until version flips the condition: “until count is greater than 5″ is the same as “while count is less than or equal to 5.”
Which should you use?
- Use
whilewhen you’re looping while something is true - Use
untilwhen you’re looping until something happens
until reads more naturally for polling or waiting:
until ping -c1 server > /dev/null 2>&1; do
sleep 1
done
echo "Server is reachable"
while reads more naturally for iteration or counters:
while [ $i -lt 10 ]; do
echo "$i"
i=$((i + 1))
done
break and continue work the same:
count=1
until [ $count -gt 5 ]; do
if [ $count -eq 3 ]; then
count=$((count + 1))
continue
fi
echo "$count"
count=$((count + 1))
done
[ 1 ]
[ 2 ]
[ 4 ]
[ 5 ]
Infinite until loop (rarely useful):
until false; do
echo "This runs forever"
sleep 1
done
false always returns 1 (failure), so the loop never exits — same as while true.
Real-world until patterns:
# Wait for a process to finish
until ! pgrep -x myservice > /dev/null; do
echo "Still running..."
sleep 5
done
echo "Process finished"
# Retry a download up to 5 times
attempt=0
until curl -sO https://example.com/file.zip || [ $attempt -ge 5 ]; do
attempt=$((attempt + 1))
echo "Retry $attempt..."
sleep 2
done
# Wait for user confirmation
until [ "$confirm" = "yes" ]; do
read -p "Type 'yes' to continue: " confirm
done
echo "Proceeding..."
Complete Example Session
# ============================================
# PART 1: BASIC WHILE LOOP
# ============================================
$ cat > count.sh << 'EOF'
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
EOF
$ chmod +x count.sh
$ ./count.sh
[ Count is 1 ]
[ Count is 2 ]
[ Count is 3 ]
[ Count is 4 ]
[ Count is 5 ]
# ============================================
# PART 2: BREAK
# ============================================
$ cat > break.sh << 'EOF'
#!/bin/bash
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
EOF
$ chmod +x break.sh
$ ./break.sh
[ Count is 1 ]
[ Count is 2 ]
[ Breaking loop at count 3. ]
# ============================================
# PART 3: CONTINUE
# ============================================
$ cat > continue.sh << 'EOF'
#!/bin/bash
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
EOF
$ chmod +x continue.sh
$ ./continue.sh
[ Count is 1 ]
[ Count is 2 ]
[ Skipping count 3. ]
[ Count is 4 ]
[ Count is 5 ]
# ============================================
# PART 4: COUNTDOWN
# ============================================
$ count=5
$ while [ $count -gt 0 ]; do
> echo "$count"
> count=$((count - 1))
> done
[ 5 ]
[ 4 ]
[ 3 ]
[ 2 ]
[ 1 ]
# ============================================
# PART 5: SUM 1 TO 10
# ============================================
$ sum=0
$ n=1
$ while [ $n -le 10 ]; do
> sum=$((sum + n))
> n=$((n + 1))
> done
$ echo "Sum: $sum"
[ Sum: 55 ]
# ============================================
# PART 6: READ FILE LINE BY LINE
# ============================================
$ printf "line1\nline2\nline3\n" > file.txt
$ while IFS= read -r line; do
> echo "Got: $line"
> done < file.txt
[ Got: line1 ]
[ Got: line2 ]
[ Got: line3 ]
# ============================================
# PART 7: NESTED LOOPS
# ============================================
$ i=1
$ while [ $i -le 3 ]; do
> j=1
> while [ $j -le 3 ]; do
> echo "$i x $j = $((i * j))"
> j=$((j + 1))
> done
> i=$((i + 1))
> done
[ 1 x 1 = 1 ]
[ 1 x 2 = 2 ]
[ 1 x 3 = 3 ]
[ 2 x 1 = 2 ]
[ 2 x 2 = 4 ]
[ 2 x 3 = 6 ]
[ 3 x 1 = 3 ]
[ 3 x 2 = 6 ]
[ 3 x 3 = 9 ]
# ============================================
# PART 8: INFINITE LOOP WITH BREAK
# ============================================
$ count=0
$ while true; do
> count=$((count + 1))
> echo "Iteration $count"
> if [ $count -ge 3 ]; then
> break
> fi
> done
[ Iteration 1 ]
[ Iteration 2 ]
[ Iteration 3 ]
# ============================================
# PART 9: BASIC UNTIL LOOP
# ============================================
$ count=5
$ until [ $count -eq 0 ]; do
> echo "$count"
> count=$((count - 1))
> done
[ 5 ]
[ 4 ]
[ 3 ]
[ 2 ]
[ 1 ]
# ============================================
# PART 10: UNTIL WITH USER INPUT
# ============================================
$ cat > ask.sh << 'EOF'
#!/bin/bash
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
EOF
$ chmod +x ask.sh
$ ./ask.sh
[ Please enter your name (or type 'exit' to quit): ]
Alice
[ Hello, Alice! ]
[ Please enter your name (or type 'exit' to quit): ]
exit
# ============================================
# PART 11: WAIT FOR A FILE
# ============================================
$ (sleep 2; touch /tmp/ready) &
$ until [ -f /tmp/ready ]; do
> echo "Waiting..."
> sleep 1
> done
$ echo "File appeared!"
[ Waiting... ]
[ Waiting... ]
[ File appeared! ]
# ============================================
# PART 12: WHILE VS UNTIL
# ============================================
# Same loop, both forms
$ count=1
$ while [ $count -le 3 ]; do echo "$count"; count=$((count+1)); done
[ 1 ]
[ 2 ]
[ 3 ]
$ count=1
$ until [ $count -gt 3 ]; do echo "$count"; count=$((count+1)); done
[ 1 ]
[ 2 ]
[ 3 ]
# ============================================
# PART 13: MENU
# ============================================
$ cat > menu.sh << 'EOF'
#!/bin/bash
while true; do
echo "1) Date"
echo "2) Uptime"
echo "3) Quit"
read -p "Choice: " c
case "$c" in
1) date ;;
2) uptime ;;
3) break ;;
*) echo "Invalid" ;;
esac
done
EOF
$ chmod +x menu.sh
$ ./menu.sh
[ 1) Date ]
[ 2) Uptime ]
[ 3) Quit ]
Choice: 1
[ Mon Jan 15 10:00:00 UTC 2024 ]
[ 1) Date ]
[ 2) Uptime ]
[ 3) Quit ]
Choice: 3
# ============================================
# PART 14: RETRY UNTIL SUCCESS
# ============================================
$ attempts=0
$ until curl -s https://example.com > /dev/null; do
> attempts=$((attempts + 1))
> if [ $attempts -ge 3 ]; then
> echo "Giving up"
> break
> fi
> echo "Retry $attempts..."
> sleep 1
> done
# ============================================
# PART 15: FULL SCRIPT
# ============================================
$ cat > loops.sh << 'EOF'
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
EOF
$ chmod +x loops.sh
$ ./loops.sh
[ Count is 1 ]
[ Count is 2 ]
[ Count is 3 ]
[ Count is 4 ]
[ Count is 5 ]
[ Count is 1 ]
[ Count is 2 ]
[ Breaking loop at count 3. ]
[ Count is 1 ]
[ Count is 2 ]
[ Skipping count 3. ]
[ Count is 4 ]
[ Count is 5 ]
[ Please enter your name (or type 'exit' to quit): ]
Alice
[ Hello, Alice! ]
[ Please enter your name (or type 'exit' to quit): ]
exit
Quick Reference
while Loop
| Command | Purpose |
|---|---|
while [ cond ]; do ... done | Loop while true |
while true; do ... done | Infinite loop |
while read -r line; do ... done < file | Read file line by line |
while IFS= read -r line | Preserve whitespace |
until Loop
| Command | Purpose |
|---|---|
until [ cond ]; do ... done | Loop until true |
until [ -f file ]; do sleep 1; done | Wait for file |
until curl URL; do sleep 1; done | Wait for service |
Loop Control
| Command | Purpose |
|---|---|
break | Exit the loop |
continue | Skip to next iteration |
break 2 | Exit 2 levels (bash 4+) |
continue 2 | Continue outer loop |
Comparison Operators in Conditions
| Operator | Meaning |
|---|---|
-eq | Equal |
-ne | Not equal |
-lt | Less than |
-le | Less or equal |
-gt | Greater than |
-ge | Greater or equal |
while vs until
| Aspect | while | until |
|---|---|---|
| Runs while | True | False |
| Stops when | False | True |
| Use for | Iteration | Waiting |
| Reads as | “While X, do Y” | “Until X, do Y” |
Common Patterns
| Pattern | Purpose |
|---|---|
while [ $i -le N ] | Count up |
while [ $i -gt 0 ] | Count down |
while true + break | Menu, retry |
until [ -f file ] | Wait for file |
while read -r line | Process file |
until curl URL | Wait for service |
Best Practices
✅ Do This:
# Always change the condition variable
while [ $i -le 5 ]; do
echo "$i"
i=$((i + 1)) # ✅
done
# Use break for early exit
while true; do
read -p "> " cmd
[ "$cmd" = "quit" ] && break
done # ✅
# Use IFS= read -r for files
while IFS= read -r line; do
echo "$line"
done < file.txt # ✅
# Increment before continue in while loops
while [ $i -le 5 ]; do
if [ $i -eq 3 ]; then
i=$((i + 1))
continue
fi
echo "$i"
i=$((i + 1))
done # ✅
# Use until for waiting
until [ -f /tmp/ready ]; do
sleep 1
done # ✅
# Add a safety limit to infinite loops
attempts=0
while true; do
attempts=$((attempts + 1))
[ $attempts -ge 10 ] && break
done # ✅
❌ Don’t Do This:
# Don't forget to increment
while [ $i -le 5 ]; do
echo "$i"
done # ❌ infinite loop
# Don't continue without incrementing
while [ $i -le 5 ]; do
if [ $i -eq 3 ]; then
continue # ❌ stuck on 3 forever
fi
i=$((i + 1))
done
# Don't read files without -r
while read line; do ...; done < f # ⚠️ backslashes eaten
# Don't use while read with a pipe if you need variables after
cat f | while read line; do
LAST="$line"
done
echo "$LAST" # ❌ empty — subshell
# Don't forget to quote in conditions
while [ $name = "exit" ]; do # ⚠️ breaks if empty
while [ "$name" = "exit" ]; do # ✅
# Don't use while for a known iteration count
i=0
while [ $i -lt 10 ]; do ...; done # ⚠️ for loop is cleaner
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Forgot increment | Infinite loop | Always increment |
continue before increment | Stuck loop | Increment first |
read without -r | Backslashes eaten | read -r |
| Pipe subshell | Variables lost | Use redirect < file |
| Unquoted variable | Breaks on empty | Quote it |
No break in menu | Can’t exit | Add a quit option |
| No safety limit | Runs forever | Add attempt counter |
| Wrong comparison | Never enters/exits | Check -lt vs -gt |
Real-World Examples
1. Count to 5
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Count is 3 ]
[ Count is 4 ]
[ Count is 5 ]
2. Break at 3
#!/bin/bash
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Breaking loop at count 3. ]
3. Skip 3
#!/bin/bash
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
[ Count is 1 ]
[ Count is 2 ]
[ Skipping count 3. ]
[ Count is 4 ]
[ Count is 5 ]
4. Until Exit
#!/bin/bash
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
5. Countdown
#!/bin/bash
count=10
while [ $count -gt 0 ]; do
echo "$count"
count=$((count - 1))
done
echo "Liftoff!"
6. Sum 1 to 100
#!/bin/bash
sum=0
n=1
while [ $n -le 100 ]; do
sum=$((sum + n))
n=$((n + 1))
done
echo "Sum: $sum"
[ Sum: 5050 ]
7. Read a File
#!/bin/bash
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
8. Wait for File
#!/bin/bash
until [ -f /tmp/ready ]; do
echo "Waiting..."
sleep 1
done
echo "Ready!"
9. Wait for Service
#!/bin/bash
until curl -s http://localhost:8080/health > /dev/null; do
echo "Service not ready..."
sleep 2
done
echo "Service is up"
10. Retry with Limit
#!/bin/bash
attempts=0
until command_that_might_fail; do
attempts=$((attempts + 1))
if [ $attempts -ge 5 ]; then
echo "Failed after 5 attempts"
exit 1
fi
echo "Attempt $attempts failed, retrying..."
sleep 2
done
11. Menu Loop
#!/bin/bash
while true; do
echo "1) Show date"
echo "2) Show disk"
echo "3) Quit"
read -p "Choice: " c
case "$c" in
1) date ;;
2) df -h ;;
3) break ;;
*) echo "Invalid" ;;
esac
done
12. Password Prompt
#!/bin/bash
attempts=0
while true; do
read -s -p "Password: " pw
echo
if [ "$pw" = "secret" ]; then
echo "Access granted"
break
fi
attempts=$((attempts + 1))
if [ $attempts -ge 3 ]; then
echo "Too many attempts"
exit 1
fi
done
13. Multiplication Table
#!/bin/bash
i=1
while [ $i -le 5 ]; do
j=1
while [ $j -le 5 ]; do
printf "%4d" $((i * j))
j=$((j + 1))
done
echo
i=$((i + 1))
done
14. Process Arguments
#!/bin/bash
while [ $# -gt 0 ]; do
echo "Argument: $1"
shift
done
15. Retry Until Success
#!/bin/bash
until ping -c1 server > /dev/null 2>&1; do
echo "Server not reachable, retrying..."
sleep 5
done
echo "Server is up"
16. Process CSV
#!/bin/bash
while IFS=, read -r name age city; do
echo "Name: $name, Age: $age, City: $city"
done < people.csv
17. Countdown with Sleep
#!/bin/bash
for i in 3 2 1; do
echo "$i..."
sleep 1
done
echo "Go!"
18. Confirm Before Action
#!/bin/bash
until [ "$ans" = "y" ] || [ "$ans" = "n" ]; do
read -p "Continue? (y/n): " ans
done
if [ "$ans" = "y" ]; then
echo "Proceeding"
fi
19. Infinite Loop with Kill Switch
#!/bin/bash
while true; do
echo "[$(date +%T)] Working..."
if [ -f /tmp/stop ]; then
echo "Stop file found, exiting"
break
fi
sleep 5
done
20. Full Script Example
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Count is $count"
count=$((count + 1))
done
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Breaking loop at count 3."
break
fi
echo "Count is $count"
count=$((count + 1))
done
count=1
while [ $count -le 5 ]; do
if [ $count -eq 3 ]; then
echo "Skipping count 3."
count=$((count + 1))
continue
fi
echo "Count is $count"
count=$((count + 1))
done
until [ "$user_input" == "exit" ]; do
echo "Please enter your name (or type 'exit' to quit):"
read user_input
if [ -z "$user_input" ]; then
echo "You did not provide any input. Please try again."
elif [ "$user_input" != "exit" ]; then
echo "Hello, $user_input!"
fi
done
Visual: while vs until
┌──────────────────────────────────────────────┐
│ while loop │
│ │
│ ┌────────────────────────────────────┐ │
│ │ condition? ──── true ────► body │ │
│ └────────┬───────────────────────────┘ │
│ │ │
│ false │
│ │ │
│ ▼ │
│ exit │
│ │
│ Runs AS LONG AS condition is true. │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ until loop │
│ │
│ ┌────────────────────────────────────┐ │
│ │ condition? ──── false ───► body │ │
│ └────────┬───────────────────────────┘ │
│ │ │
│ true │
│ │ │
│ ▼ │
│ exit │
│ │
│ Runs UNTIL condition becomes true. │
│ │
└──────────────────────────────────────────────┘
Visual: break and continue
┌──────────────────────────────────────────────┐
│ break │
│ │
│ iteration 1 ✓ │
│ iteration 2 ✓ │
│ iteration 3 → break → exit loop │
│ iteration 4 (never runs) │
│ iteration 5 (never runs) │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ continue │
│ │
│ iteration 1 ✓ │
│ iteration 2 ✓ │
│ iteration 3 → continue → skip to next │
│ iteration 4 ✓ │
│ iteration 5 ✓ │
│ │
└──────────────────────────────────────────────┘
Summary
| Concept | Syntax | Example |
|---|---|---|
| while | while [ cond ]; do ... done | while [ $i -le 5 ]; do ...; done |
| until | until [ cond ]; do ... done | until [ -f f ]; do sleep 1; done |
| Infinite | while true | while true; do ...; done |
| break | break | Exit the loop |
| continue | continue | Skip to next iteration |
| break N | break 2 | Exit N levels |
| continue N | continue 2 | Continue outer loop |
| Read file | while read -r line | while IFS= read -r line; do ...; done < f |
| Process args | while [ $# -gt 0 ] | while [ $# -gt 0 ]; do ...; shift; done |
| Retry | until command | until curl URL; do sleep 1; done |
Key takeaways:
whileruns while the condition is true;untilruns until the condition becomes true- Both check the condition before each iteration — the body may run zero times
- Always change something inside the loop so the condition eventually becomes false
breakexits the loop immediately;continueskips to the next iteration- In a
whileloop, increment beforecontinueor you’ll loop forever on the same value - Use
while truewith abreakfor menus and retry loops - Use
untilfor polling — waiting for a file, a service, or a condition - Use
while IFS= read -r lineto read files line by line - Use
break 2andcontinue 2to control nested loops (bash 4+) - Add a safety limit to any infinite loop — a counter or a max attempts check
- Redirect input with
done < fileinstead of piping — avoids subshell variable loss
Remember: Loops are how you repeat work. while says “keep going while this is true.” until says “keep going until this becomes true.” Both need something to change inside — forget that and you’ve written an infinite loop. Use break to exit early and continue to skip ahead. For files, use while IFS= read -r. For waiting, use until. Master these two loops, and you can handle any repetitive task in shell scripting.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!