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

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.