Bash scripting offers a variety of loops that allow you to repeatedly execute a sequence of commands. Whether you're a beginner in bash scripting or an experienced developer, understanding how to use loops effectively is a fundamental skill. In this comprehensive guide, we will explore different types of loops in bash, their applications, and provide examples to help you master the art of loop scripting.
This is part of my series on bash. Look at all the articles over here.
Introduction to Loops in Bash
Loops form an essential part of bash scripting, allowing you to perform repetitive tasks efficiently. They enable you to iterate through lists, arrays, files, and even command outputs, executing a set of instructions for each iteration. Bash provides several types of loops, each tailored to specific scenarios.
The Basic For Loop
The basic for
loop is your starting point in loop scripting. It iterates over a range of values and performs actions for each value. Consider the following example:
for i in {1..5}; do
echo "Number: $i"
done
Output:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
In this loop, the variable i
takes values from 1 to 5, and the echo
command displays each number along with the descriptive text "Number: ". This type of loop is particularly useful when you need to execute a specific action a predetermined number of times.
To learn about braces expansion in bash (). Look at this article.
Looping Through Arrays
Arrays are fundamental data structures in bash, and you can use loops to iterate through their elements. Take a look at this example:
fruits=("apple" "banana" "orange")
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
Output:
Fruit: apple
Fruit: banana
Fruit: orange
This loop cycles through the elements of the fruits
array, displaying each fruit's name along with "Fruit: ". This approach is beneficial when you want to process each element in an array individually.
Note: Here echo
command is being used to print on terminal. Learn more about echo in detail in this article.
The Versatile While Loop
The while
loop continuously executes a block of code as long as a specific condition remains true. Here's an example:
count=1
while [ $count -le 3 ]; do
echo "Count: $count"
count=$((count+1))
done
Output:
Count: 1
Count: 2
Count: 3
In this instance, the loop prints the value of count
as long as it is less than or equal to 3. The while
loop is ideal for scenarios where the number of iterations is not predetermined.
The Purpose of the Until Loops in bash
The until
loop is the counterpart of the while
loop; it continues executing until a given condition becomes true. Consider this illustration:
num=0
until [ $num -ge 5 ]; do
echo "Number: $num"
num=$((num+1))
done
Output:
Number: 0
Number: 1
Number: 2
Number: 3
Number: 4
Here, the loop prints the value of num
until it becomes greater than or equal to 5. The until
loop is advantageous when you want to repeat a task until a specific criterion is met.
Iterating Through Files with Loops
Looping through files is a common scenario in bash scripting. The following example showcases this:
for i in '/home/ajay/Videos/OP/1063.mkv' '/home/ajay/Videos/OP/1064.mkv' '/home/ajay/Videos/OP/1065.mkv'
do
ffmpeg -i "$i" -codec:v libx265 "${i}_x265.mkv"
done
This loop compresses each video file using ffmpeg*. It's a handy technique when you need to perform batch operations on files.
To learn more about ffmpeg compression of videos and images, look at this article.
Adding Incremental Steps to Loops in bash
Loops can include incremental steps to control the iteration process. Observe this example:
for ((i=0; i<10; i+=2)); do
echo "Step: $i"
done
Output:
Step: 0
Step: 2
Step: 4
Step: 6
Step: 8
Here, the loop iterates through numbers starting from 0, increasing by 2 in each iteration. This feature is valuable for scenarios where you need to process every nth element.
Looping Through Command Output
Looping through the output of commands is another valuable capability of bash loops. Consider the following script:
for file in $(ls *.txt)
do
echo "Text File: $file"
done
Output:
Text File: ascii.txt
Text File: file_1.txt
Text File: file1.txt
Text File: file_2.txt
Text File: file_3.txt
Text File: file_4.txt
Text File: file_5.txt
Text File: file.txt
Text File: romeo.txt
Text File: sample.txt
Text File: test.txt
Text File: unicode.txt
Text File: utf8.txt
In this example, the loop goes through the output of the command ls *.txt
and prints them. This technique is useful when you want to process data generated by a command.
Implementing Conditional Loops in bash
Conditional loops combine loops and conditional statements to execute commands based on specific criteria. Take a look at this illustration:
for num in {1..5}; do
if [ $num -gt 2 ]; then
echo "Number: $num"
fi
done
Output:
Number: 3
Number: 4
Number: 5
This loop prints numbers greater than 2. It's an effective approach when you need to filter elements during iteration.
Skipping Iterations with the continue
Statement
The continue
statement allows you to skip iterations within a loop based on certain conditions. Explore this example:
for num in {1..5}; do
if [ $num -eq 3 ]; then
continue
fi
echo "Number: $num"
done
Output:
Number: 1
Number: 2
Number: 4
Number: 5
In this loop, the iteration with the value 3 is skipped due to the continue
statement. This feature is handy for excluding specific cases from processing.
Breaking Out of Loops with the break
Statement in bash
The break
statement provides a way to prematurely exit a loop based on certain conditions. Consider this example:
for num in {1..5}; do
if [ $num -eq 4 ]; then
break
fi
echo "Number: $num"
done
Output:
Number: 1
Number: 2
Number: 3
The loop terminates when the value of num
becomes 4. The break
statement is useful for stopping execution once a particular condition is met.
Looping through File content
Bash loops can also operate on data from files. The following script showcases this technique.
[ajay@legion Pictures]$ cat numbers.txt
5
8
3
9
2
while read -r number; do
echo "Number: $number"
done < numbers.txt
Output:
Number: 5
Number: 8
Number: 3
Number: 9
Number: 2
Here, the loop reads numbers from the numbers.txt
file and prints them using echo
. This approach is useful for processing data from external sources.
Expanding Horizons: Looping Through Multiple Ranges
Bash loops can handle more complex scenarios, such as iterating through multiple ranges. This example demonstrates the concept:
for i in ~/{f..b}/Downloads/{1..-2}; do
echo $i
done
Output:
/home/ajay/f/Downloads/1
/home/ajay/f/Downloads/0
/home/ajay/f/Downloads/-1
/home/ajay/f/Downloads/-2
/home/ajay/e/Downloads/1
/home/ajay/e/Downloads/0
/home/ajay/e/Downloads/-1
/home/ajay/e/Downloads/-2
/home/ajay/d/Downloads/1
/home/ajay/d/Downloads/0
/home/ajay/d/Downloads/-1
/home/ajay/d/Downloads/-2
/home/ajay/c/Downloads/1
/home/ajay/c/Downloads/0
/home/ajay/c/Downloads/-1
/home/ajay/c/Downloads/-2
/home/ajay/b/Downloads/1
/home/ajay/b/Downloads/0
/home/ajay/b/Downloads/-1
/home/ajay/b/Downloads/-2
In this intricate loop, multiple ranges are combined to generate a variety of paths. This technique is particularly useful when you need to work with dynamic data patterns.
Creative Usage: Creating a Timer with Loops
Loops can be creatively employed for various tasks. Here's an example script* of using loops to create a simple timer:
#!/bin/bash
# convert time into seconds
time="$(echo "$@" | sed 's/h/*3600+/g;s/m/*60+/g;s/s/*1+/g;s/+$//' | bc | sed 's/\..*//')"
# print the remaining time
for ((i=1;i<=time;i=i+1))
do
printf '\033[0K%s\r' "$(((time-i)/60)):$(((time-i)%60))"
sleep 1
done
Output:
23:56
For this to work, first you need to create a script with a name, say timer.sh. To learn about how to work with script, look over here.
This script accepts input in hours, minutes, and seconds, converts it to seconds, and then creates a countdown timer that prints the remaining time in the format "minutes:seconds" (ex - 23:56
-> 23:55
-> 23:54
...).
You can run commands like timer.sh 1h 3s
or timer.sh 30m 5m 2s
.
You can also append a music after the loop using ffplay
and/or add a notification using notify-send
, to get notification and/or music after the time is over.
It's a unique example of how loops can be applied to creative real-world scenarios.
Conclusion
Loops are the backbone of bash scripting, empowering you to automate repetitive tasks and manage complex operations. Whether you're iterating through arrays, files, or command outputs, understanding the different types of loops and their applications is essential. By mastering loop scripting in bash, you unlock the potential to create efficient and robust automation solutions for various scenarios. For official guide from GNU, look at this manual.