Repeating Instructions With Loops in Bash
16 min read·Jan 1, 2025
In programming, a loop statement is a control structure used to repeat the execution of a set of instructions multiple times until a certain condition is met.
The while loop
The while loop is used to execute a set of instructions specified between the do and done keywords, for as long as the condition remains true.
while [[ condition ]];
do
instructions
done
This structure is often used to create long-running processes or to process data of unknown length.
Note: In programming, the cycle in which a loop executes its instructions — whether partially or completely — is called an iteration. For example, if a loop executes the specified instructions 3 times, we'll say that it performed 3 iterations.
Example
Let's consider this script, that outputs the elements of an array of strings:
#!/bin/bash
guests=("John Doe" "James Higgins" "Alice Peterson")
total=${#guests[@]}
index=0
while [[ $index -ne $total ]];
do
echo "$index -> ${guests[$index]}"
index=$(($index + 1))
done
When executed, it will:
- Declare a variable named
guestsand initialize it with an array of strings. - Declare a variable named
totaland initialize it to the number of elements in theguestsarray. - Declare a variable named
indexand initialize to0. - Start a loop that runs while the value of the
indexvariable is not equal to the value of thetotalvariable. - Output the value of the
indexvariable and the value of the element in theguestsarray at this index. - Increment the value of the
indexvariable by1. - Re-run the loop from step 5.
Which will produce this output:
$ ./script.sh
0 -> John Doe
1 -> James Higgins
2 -> Alice Peterson
The until loop
The until loop is used to execute a set of instructions specified between the do and done keywords, until the condition becomes true.
until [[ condition ]];
do
instructions
done
Example
Let's consider this script, that outputs the value of a variable and decrements it at every iteration:
#!/bin/bash
counter=3
until [[ $counter -lt 1 ]]; do
echo "Countdown: $counter"
counter=$((counter - 1))
done
echo "Blast off!"
When executed, it will:
- Declare a variable named
counterand initialize it to3. - Evaluate whether the value of the
countervariable is lesser than1. - If
true, terminate theuntilloop. - If
false, output the current value of thecountervariable and decrease it by1. - Re-run the
untilloop from step 2.
Which will produce this output:
$ ./script.sh
Countdown: 3
Countdown: 2
Countdown: 1
Blast off!
The for loop
The for loop is used to execute a set of instructions a predetermined number of times based on a known list of items or range.
Iterating on a list
In its first form, the for loop iterates over a list of items, such as an array of strings or numbers, and executes the instructions specified between the do and done keywords for each item until there are no more items in the list.
for item in list;
do
instructions
done
Where:
itemis an arbitrary variable name that can be used in the instructions declared between thedoanddonekeywordslistis a list of values separated by a space character, generated either manually or automatically.
Note: If the
in listexpression is not specified, theforloop assumes that thelistis composed of the positional arguments of the script, as ifin "$@"had been specified.
Example
Let's consider this script, that extracts and outputs the email address of a list of users contained in an array:
#!/bin/bash
users=("John Doe,johndoe@mail.com" "Alice Fisher,a.fisher@mail.com" "Bob Burnquist,bbquist@mail.com")
for user in "${users[@]}";
do
echo "$user" | cut -d ',' -f 2
done
When executed, it will:
- Define a variable named
usersand initialize it with an array of strings. - Define a variable named
userand initialize it with the value of the next element in theusersarray. - Split the current value of the
uservariable using','as a delimiting character and output the second part of the string. - Re-run the
forloop from step 2.
Which will produce this output:
$ ./script.sh
johndoe@mail.com
a.fisher@mail.com
bbquist@mail.com
Note:
The values of a list can also be automatically generated using a shell expansion, such as a brace expansion, a command substitution, and so on.
For example:
# Shell expansion for i in {1..3} # Command substitution for i in $(seq 1 3)
Iterating on a condition
In its second form inspired from the C language, the for loop executes a set of instructions until its conditional expression evaluates to false.
for (( init ; cond ; iter ));
do
instructions
done
Where:
initis an initialization expression that is executed once at the beginning of the loop and is typically used to set the initial values for loop control variables.condis a conditional expression that is evaluated before each iteration of the loop and will keep the loop running until it evaluates tofalse.iteris an iteration expression that is executed at the end of each iteration and is typically used to update loop control variables.
Example
Let's consider this script, that outputs all the possible combinations between two arrays of strings:
#!/bin/bash
first_names=("John" "Alice" "Bob")
last_names=("Doe" "Smith" "Johnson")
for ((i = 0; i < ${#first_names[@]}; i++));
do
for ((j = 0; j < ${#last_names[@]}; j++));
do
echo "${first_names[i]} ${last_names[j]}"
done
done
When executed, it will:
- Define a variable named
first_namesand initialize it with an array of strings. - Define a variable named
last_namesand initialize it with an array of strings. - Start a first
forloop that iterates on each index of thefirst_namesarray. - Start a nested
forloop that iterates on each index of thelast_namesarray. - Output the current value of the
first_namesarray concatenated to the current value of thelast_namesarray.
Which will produce this output:
$ ./script.sh
John Doe
John Smith
John Johnson
Alice Doe
Alice Smith
Alice Johnson
Bob Doe
Bob Smith
Bob Johnson
Note: In Bash, the
variable++syntax is a shorthand for increasing the value of a variable by1(i.e. incrementing), which is equivalent tovariable=$(($variable + 1)).
Terminating and skipping loop iterations
In Bash, the break and continue statements allow you to control the execution flow of loops by either terminating them prematurely or skipping some iterations.
The break statement
The break statement is used to immediately terminate the current iteration of a loop, regardless of whether the loop's condition is met or not.
# for / while / until
do
if [[ condition ]]; then
break
fi
instructions
done
Example
Let's consider this script, that checks the validity of email addresses:
#!/bin/bash
emails=("$@")
for email in "${emails[@]}"; do
if [[ ! "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]];
then
echo "Invalid email address: $email"
break
fi
done
When executed, it will:
- Declare a variable named
emailsand initialize it with an array containing the list of positional arguments of the script. - Loop on each element of the
emailsarray and store the value of the current element into theemailvariable. - Check if the value of the
emailvariable matches the specified regular expression. - If
false, output the value of theemailvariable and terminate the loop using thebreakstatement.
Which will produce this output:
$ ./script.sh johndoe@mail.com a.ghallan@mail.com bobfisher03 martin.gould@mail.com
Invalid email address: bobfisher03
The continue statement
The continue statement is used to skip the current iteration of a loop and directly proceed to the next iteration, without executing the remaining instructions.
# for / while / until
do
if [[ condition ]]; then
continue
fi
instructions
done
Example
Let's consider this script, that outputs the filenames of the entries of the current working directory with a .js file extension:
#!/bin/bash
for file in *;
do
if [[ ! $file == *.js ]]; then
continue
fi
echo $file
done
When executed, it will:
- Loop on each file present in the current directory and store the name of the current file in the
filevariable. - Check if the value of the
filevariable ends with".js". - If
true, skip the current loop iteration without executing the following instructions using thecontinuekeyword. - If
false, output the current filename using theechocommand. - Re-run the loop from step 1.
Which will produce this output:
$ ls
index.js package.json script.sh
$ ./script.sh
index.js
Summary
Here's a summary of what you've learned in this lesson:
- The
whileloop executes a set of instructions for as long as the specified condition remainstrue. - The
untilloop executes a set of instructions until the specified condition becomestrue. - The
forloop iteratively executes a set of instructions a predetermined number of times based on a known list of items or range. - The
breakstatement is used to immediately terminate the current loop, regardless of whether the loop's condition is met or not. - The
continuestatement is used to skip the current iteration of a loop and directly proceed to the next iteration, without executing the remaining instructions.
Enjoying the courses?
I've made these courses completely free so anyone can learn from them. If they've helped you and you'd like to actively support the work behind BackendBrewery, you can leave a tip:
Support BackendBrewery