Loops in Linux shell scripts is something you will inevitably face once writing more complex scenarios. They are nothing new for those who have at least some sort of programming experience, since they exist in pretty much any programming language. Loops are control structures to repeatedly execute a block of code as long as a specified condition is true. They are essential for automating repetitive tasks and processing large amounts of data efficiently. Since loops are a fundamental programming concept, they of course exist in bash (or any other shell).
Two main types of loops in Linux
As in pretty much any other programming or scripting language, there are two main types of loops: for
and while
. There can be overlap in their use cases, and the choice between them ultimately depends on the specific requirements of the task at hand and the programmer’s preference for clarity and readability.
for
Use a for
loop when the number of iterations is known or can be determined in advance. This could be when you need to iterate over a fixed range of values, such as elements in an array or a predefined set of values. for
loops are especially useful when you need to perform a specific action a fixed number of times.
while
Use a while
loop when the number of iterations is not known beforehand or is dynamic, based on some condition. This could be when you need to continue iterating until a certain condition is met or until a user input meets specific criteria. while
loops are particularly useful for situations where the loop needs to run indefinitely until a certain condition becomes false. Example use cases include reading input from a user until a specific value is entered, processing data until reaching the end of a file, or continuously checking for certain conditions in real-time systems.
Examples
for
works nicely in combination with seq
which prints a sequence of numbers. You can also use brace expansion {1..10}
. Here is a trivial for
example which will print numbers 1 to 10:
[root@linux ~]# for i in $(seq 1 10); do echo "${i}"; done
1
2
3
4
5
6
7
8
9
10
[root@linux ~]#
And here is the while
example which will print all lines of given file one by one:
[root@linux ~]# while read line; do echo "${line}"; done < demo.txt
this
is
demo
file
[root@linux ~]#
Note in this example file has empty lines. What if we want to skip them?
Skipping the iteration
continue
statement is used to skip the current iteration of a loop and proceed to the next iteration. It’s often used within loops to skip certain iterations based on specific conditions.
You can use it like:
[root@linux ~]# while read line; do [[ "${line}" == "" ]] && continue; echo "${line}"; done < demo.txt
this
is
demo
file
[root@linux ~]#
Note that for better readability, shorthand if syntax is used here.
continue
is also useful in nested loops (loop inside a loop). If number is given for continue
(like continue 2
), it will be used to skip the current iteration of the inner loop and continue with the next iteration of the outer loop when working with nested loops. This skips the remaining iterations of the inner loop and jumps to the next iteration of the outer loop. Here’s an example demonstrating the use of continue 2
in a nested loop:
#!/bin/bash
# nested loop example
for outer in {1..3}; do
echo "Outer loop iteration: ${outer}"
for inner in {1..5}; do
# skip even numbers in the inner loop
if [ $((inner % 2)) -eq 0 ]; then
continue 2
fi
echo "Inner loop iteration: ${inner}"
done
done
exit 0
So in this example, inner loop will never print anything but “1”, since next number is “2” which is even number and script immediately continues to outer loop:
[root@linux ~]# ./loop.sh
Outer loop iteration: 1
Inner loop iteration: 1
Outer loop iteration: 2
Inner loop iteration: 1
Outer loop iteration: 3
Inner loop iteration: 1
[root@linux ~]#
Breaking the loop
Sometimes you may want not to skip the iterations based on some criteria, but rather terminate a loop prematurely (before initial given condition is met). For this, you should use break
statement. Going back to the initial example, it will break the loop at first met empty line:
[root@linux ~]# while read line; do [[ "${line}" == "" ]] && break; echo "${line}"; done < demo.txt
this
[root@linux ~]#
Similar to continue
, break
can also be used in nested loops. After the inner loop terminates, the outer loop continues its iterations. In fact, given that you have 4 loops nested, break
will be equal to continue 2
, break 2
will be equal to continue 3
and so on.
Loops in Linux are essential for automating repetitive tasks and processing large amounts of data efficiently. Loops allow to write concise and organized code by avoiding the need for redundant code. Overall, loops are versatile constructs that play a crucial role in programming by enabling efficient iteration and automation of tasks across various domains and applications.