When you’re learning to code, loops are one of those things that tend to trip people up a few times before they get the hang of it. There are a few different types of loops, but today we’re going to focus on the “for” loop.

I’m going to use bash for all the demonstrations in this tutorial, however the concepts of “for” loops are generally the same across multiple languages. What differs is the “syntax” of the language. The syntax is just the overall “structure” of how the language, or code, is laid out. So once you understand the concepts, you’ll be able to use “for” loops regardless of the programming language you want to learn.

Table of Contents

The For Loop

Structure

The basic structure of a “for” loop is as follows:

“for” a set of conditions, do an action, repeat until finished.

Example 1: A basic for loop

single-for-loop.sh
  • bash
1
2
3
4
5
6
7
#!/bin/bash

for (( i=0; i<3; i++ ))
    do
        # Output the number of the current loop
        echo "Loop number is: $i"
    done

Let’s break this down. Here are the conditions of the “for” loop. As long as these conditions are “true”, the action will execute.

Conditions:

  • i=0
    • set the variable “i” to be 0 (zero)
  • i<3
    • do as long as “i” is less than 3
  • i++
    • increase “i” by 1
  • do
    • echo “Loop number: $i”
      • This is the command that will run every time the loop runs. We’re just having it display the current loop number so you can see visually how it works. Because “i” is a variable you can use it in your code.
  • done
    • Specifies the “end” of the loop when the conditions are no longer met

Output

$ bash single-for-loop.sh 
Loop number is: 0
Loop number is: 1
Loop number is: 2

The loop ran for three times; 0, 1, and 2, because on the fourth run, “i” was set to “3” which is no longer less than “3” so the loop ends.

Example 2: Basic for loop, incrementing by 10

In the first example, we could use the variable “i” to represent the loop number as “i” incremented by 1 for each pass through the loop. In the following example, let’s increment “i” by 10.

single-for-loop-10.sh
  • bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

count=0
for (( i=0; i<40; i+=10 ))
    do
        # Output the number of the current loop
        echo "Loop number is: $count"

        # Output the value of "i"
        echo "Value of i is: $i"

        # Increase the count by 1
        count=$(($count +1))
    done

For every pass through the loop this time, “i” increases in value by 10. Because of this, we can’t use the value of “i” to represent the number of times through the loop, because on the third time through “i” already has a value of 20.

In order to be able to display each pass through the loop this time, I had to use another variable that I called “count”.

“count” was assigned a value of 0 (zero) outside of the loop, and every pass through its value was incremented by 1.

Output

$bash single-for-loop-10.sh 
Loop number is: 0
Value of i is: 0
Loop number is: 1
Value of i is: 10
Loop number is: 2
Value of i is: 20
Loop number is: 3
Value of i is: 30

Syntax “Style”

“For” loops in bash can be written in two different ways:

As a single-line command

$ for (( i=0; i<3; i++ )); do echo "Hello? Is anyone out there?"; done
Hello? Is anyone out there?
Hello? Is anyone out there?
Hello? Is anyone out there?

or as a multi-line command

  • bash
1
2
3
4
for (( i=0; i<3; i++ ))
    do 
        echo "Hello? Is anyone out there?"
    done

Output

Hello? Is anyone out there?
Hello? Is anyone out there?
Hello? Is anyone out there?

Both of these “for” loops are exactly the same. The first “style” tends to be used when using a “for” loop directly on the command line, while the second style tends to be used in scripts as it’s a little easier to see what’s happening in the loop. Both are equally valid.

Conditions

A “for” loop can include many different kinds of conditions or criteria. So far, we’ve only seen “for” loops use a single incrementing number.

“For” loops are so much more powerful than that however, as you can also use conditions in a “set”.

Example 3: Make 5 new folders called “January”, “March”, “May”, “July”, and “August” and…

…Inside each folder make 3 folders called “phone”,“light”, and “rent” using a single command.

Now you could sit there and type out the following command which would work, but it’s very repetitive, time-consuming, and prone to mistakes.

mkdir -p January/phone January/light January/rent March/phone March/light March/rent etc.

I didn’t type out the entire command above but you can see where it’s going. If a process is repetitive, that means it can be tackled using a loop.

$ for month in January March May July August; do for dir in phone light rent; do echo "mkdir -p $month/$dir"; done; done

There are a couple of things you should notice about the above “for” loop:

  1. There are two “for” loops. These are called “nested” “for” loops and we’ll get into them later on in this tutorial.
  2. I didn’t use the variable “i”. The variable “i” was arbitrary, you can name the variable whatever you like. It’s best to keep it descriptive.
  3. I put the “mkdir” command inside of an “echo” command so that we would be able to see the output of what the “for” loop was going to do instead of having it actually make the folder. To have it make the folder, you would remove the “echo” and the opening and closing quotation marks (") around the “mkdir” command.

Output

mkdir -p January/phone
mkdir -p January/light
mkdir -p January/rent
mkdir -p March/phone
mkdir -p March/light
mkdir -p March/rent
mkdir -p May/phone
mkdir -p May/light
mkdir -p May/rent
mkdir -p July/phone
mkdir -p July/light
mkdir -p July/rent
mkdir -p August/phone
mkdir -p August/light
mkdir -p August/rent

The following are other types of conditions that you can use with “for” loops in bash.

Using an inclusive range of ascending numbers

$ for i in {8..11}; do echo $i; done
8
9
10
11

Using an inclusive range of decending numbers

$ for i in {8..5}; do echo $i; done
8
7
6
5

Using items in a set

$ for i in March September; do echo "$i"; done
March
September

Using a range with an increment

$ for i in {0..10..2}; do echo "$i"; done
0
2
4
6
8
10

Using a for loop to iterate over items in an array

$ Movies=("Contact" "The Mask of Zorro" "Terminator" "Pitch Black" "Congo")
$ for movie in "${Movies[@]}"; do echo "Movie: $movie"; done
Movie: Contact
Movie: The Mask of Zorro
Movie: Terminator
Movie: Pitch Black
Movie: Congo

Nested For Loops

A “nested” “for” loop consists of an “outer” “for” loop and one or more “inner” “for” loops. The inner loop will run fully for every one completion of the outer loop.

Let’s see how this works:

Example 4: a nested for loop

double-nested-for-loop.sh
  • bash
1
2
3
4
5
6
7
8
9
10
#!/bin/bash

for (( i=0; i<3; i++ ))
    do
        echo "i loop: $i"
        for (( j=0; j<5; j++ ))
            do
                echo "    j loop: $j"
            done
    done

In this case, the “inner” loop will run 5 times for every 1 run of the “outer” loop, which will run 3 times.

Output

$ bash double-nested-for-loop.sh 
i loop: 0
    j loop: 0
    j loop: 1
    j loop: 2
    j loop: 3
    j loop: 4
i loop: 1
    j loop: 0
    j loop: 1
    j loop: 2
    j loop: 3
    j loop: 4
i loop: 2
    j loop: 0
    j loop: 1
    j loop: 2
    j loop: 3
    j loop: 4

You can nest as many “for” loops together as you want, you just need to keep in mind that the inner most loop will complete before the execution travels “back out” to the next loop up.

Here’s an example with 3 nested loops.

Example 5: 3 nested loops

triple-nested-for-loop.sh
  • bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

for (( i=0; i<3; i++ ))
    do
        echo "i loop: $i"
        for (( j=0; j<5; j++ ))
            do
                echo "    j loop: $j"
                for (( k=10; k<40; k+=10 ))
                    do  
                        echo "        k loop: $k"
                    done
            done
    done

Output

$ bash triple-nested-for-loop.sh
i loop: 0
    j loop: 0
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 1
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 2
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 3
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 4
        k loop: 10
        k loop: 20
        k loop: 30
i loop: 1
    j loop: 0
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 1
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 2
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 3
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 4
        k loop: 10
        k loop: 20
        k loop: 30
i loop: 2
    j loop: 0
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 1
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 2
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 3
        k loop: 10
        k loop: 20
        k loop: 30
    j loop: 4
        k loop: 10
        k loop: 20
        k loop: 30

Conclusion

“For” loops aren’t difficult, but they can take a little bit of practice before you wrap your head around how to use them. Once you get the hang of it though, you can use “for” loops for solving many different kinds of problems. You’ll also likely reduce long, boring, repetitive tasks down to a few minutes as well. Who wouldn’t love that?

If you have any questions/comments please leave them below.

Thanks so much for reading ^‿^

Claire

If this tutorial helped you out please consider buying me a pizza slice!