Loops in Bash
Beware of infinite loops!
The ability to loop is a very powerful feature of bash scripting. Loops have a variety of use cases.
In this tutorial, you will explore the three different bash loop structures. You will also learn how to use loops to traverse array elements.
Furthermore, you will learn how to use break and continue statements to control loops, and finally, you will learn how to create infinite loops.
For Loops in Bash
For loops are one of three different types of loop structures that you can use in bash. There are two different styles for writing a for loop.
- C-styled for loops
- Using for loop on a list/range of items
C-style For Loops in Bash
If you are familiar with a C or C++ like programming language, then you will recognize the following for loop syntax:
for ((initialize ; condition ; increment)); do
[COMMANDS]
done
Using the aforementioned C-style syntax, the following for loop will print out “Hello Friend” ten times:
for ((i = 0 ; i < 10 ; i++)); do
echo "Hello Friend"
done
The for loop first initialized the integer variable i to zero then it tests the condition (i <10); if true, then the loop executes the line echo “Hello Friend” and increments the variable i by 1, and then the loop runs again and again until i is no longer less than 10.
kabary@handbook:~$ bash hello.sh
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
Hello Friend
List/Range For Loops in Bash
Another syntax variation of for loop also exists that is particularly useful if you are working with a list of files (or strings), range of numbers, arrays, output of a command, etc. The list/range syntax for loop takes the following form:
for item in [LIST]; do
[COMMANDS]
done
For example, the following for loop does exactly the same thing as the C-style for loop you had created in the previous section:
for i in {1..10}; do
echo "Hello Friend"
done
The var.sh script below will output all the files and directory that exists under the /var directory:
#!/bin/bash
for i in /var/*; do
echo $i
done
Below is sample output when you run the var.sh script:
kabary@handbook:~$ ./var.sh
/var/backups
/var/cache
/var/crash
/var/lib
/var/local
/var/lock
/var/log
/var/mail
/var/metrics
/var/opt
/var/run
/var/snap
/var/spool
/var/tmp
While Loops in Bash
The while loop is another popular and intuitive loop you can use in bash scripts. The general syntax for a bash while loop is as follows:
while [ condition ]; do
[COMMANDS]
done
For example, the following 3x10.sh script uses a while loop that will print the first ten multiples of the number three:
#!/bin/bash
num=1
while [ $num -le 10 ]; do
echo $(($num * 3))
num=$(($num+1))
done
Here's the output of the above script:
kabary@handbook:~$ ./3x10.sh
3
6
9
12
15
18
21
24
27
30
It first initialized the num variable to 1; then, the while loop will run as long as num is less than or equal to 10. Inside the body of the while loop, echo command prints of num multiplied by three and then it increments num by 1.
Until Loops in Bash
If you are coming from a C/C++ background, you might be looking for a do-while loop but that one doesn't exist in bash.
There is another kind of loop that exists in bash. The until loop follows the same syntax as the while loop:
until [ condition ]; do
[COMMANDS]
Done
The key difference between until loop and while loop is in the test condition. A while loop will keep running as long as the test condition is true; on the flip side, an until loop will keep running as long as test condition is false!
For example, you can easily create the 3x10.sh script with an until loop instead of a while loop; the trick here is to negate the test condition:
#!/bin/bash
num=1
until [ $num -gt 10 ]; do
echo $(($num * 3))
num=$(($num+1))
done
Notice that the negation of the test condition [ $num -le 10 ]; is [ $num -gt 10 ];
More on looping in bash scripts
Now that you are familiar with the loops in the bash scripts
Print the contents of an array in bash
If you are following this tutorial series from start, you should be familiar with arrays in bash.
For loops are often the most popular choice when it comes to iterating over array elements.
For example, the following prime.sh script iterates over and prints out each element in the prime array:
#!/bin/bash
prime=(2 3 5 7 11 13 17 19 23 29)
for i in "${prime[@]}"; do
echo $i
done
This is the output of the prime.sh script:
kabary@handbook:~$ ./prime.sh
2
3
5
7
11
13
17
19
23
29
Using Break and Continue in bash loops
Sometimes you may want to exit a loop prematurely or skip a loop iteration. To do this, you can use the break and continue statements.
The break statement terminates the execution of a loop and turn the program control to the next command or instruction following the loop.
For example, the following loop would only print the numbers from one to three:
for ((i=1;i<=10;i++)); do
echo $i
if [ $i -eq 3 ]; then
break
fi
done
You can also use a continue statement to skip a loop iteration. The loop continues and moves to the next iteration but the commands after the continue statements are skipped in that partcular iteration.
For example, the following odd.sh script would only print the odd numbers from one to ten as it skips over all even numbers:
#!/bin/bash
for ((i=0;i<=10;i++)); do
if [ $(($i % 2)) -ne 1 ]; then
continue
fi
echo $i
done
Here's the output that prints odd numbers:
kabary@handbook:~$ ./odd.sh
1
3
5
7
9
Infinite Loops in bash
An infinite loop is a loop that keeps running forever; this happens when the loop test condition is always true.
In most cases, infinite loops are a product of a human logical error.
For example, someone who may want to create a loop that prints the numbers 1 to 10 in descending order may end up creating the following infinite loop by mistake:
for ((i=10;i>0;i++)); do
echo $i
done
The problem is that the loop keeps incrementing the variable i by 1. To fix it, you need to change i++ with i-- as follows:
for ((i=10;i>0;i--)); do
echo $i
done
In some cases, you may want to intentionally create infinite loops to wait for an external condition to be met on the system. You can easily create an infinite for loop as follows:
for ((;;)); do
[COMMANDS]
done
If you want to create an infinite while loop instead, then you can create it as follows:
while [ true ]; do
[COMMANDS]
done
Awesome! This brings us to the end of this tutorial in the Bash Beginner Series. I hope you have enjoyed making looping around in bash!
Now practice the looping with some simple exercises. You also get the solution in the PDF below.
Have a look at the next chapter as you will learn how to reuse code in you bash scripts by creating functions.