Some Noticeable Information
The Bash for loop is a versatile tool that can work with numbers, words, arrays, command line variables, or the output of other commands.
For each value in a list, simple for loops can be utilized to repeat a specific code section. It is possible to employ the for loop with numerical lists, word lists, number ranges, filenames, command line parameters, word arrays, and associative arrays, thus granting versatility in scripting tasks.
The versatile Bash for loop does much more than loop around a set number of times. We describe its many variants so you can use them successfully in your own Linux scripts.
The for Loop
All scripting and programming languages have mechanisms for handling loops, which are sections of code executed repeatedly. Instead of manually typing the same set of instructions multiple times, loops allow for the repetition of a specific section of code.
The Bash for loop is highly versatile as it can operate with numbers, words, arrays, command line variables, or the output of other commands. These elements are specified in the loop's header, which determines the type of data the loop processes (such as numbers or strings) and the condition that eventually terminates the looping.
The loop body encompasses the code to be repeated, specifying the actions the loop should perform. It can include any valid script command.
To iterate through a range of values or a list of data items, a variable known as the loop counter or iterator is employed. The iterator assumes the value of each successive number, string, or data type being iterated over. This enables the loop to operate on the values of each data item sequentially, and in certain scenarios, manipulate the data items themselves.
Simple for Loops
If you're looking to write your first for loop, these simple examples will get you started.
for Loops using Numerical Lists
A for loop can be executed on the command line by using a specific command. This command is responsible for creating and running a basic for loop. The iterator in this loop is defined as a variable named "i". Each value in the list of numbers will be assigned to "i" one by one. During each iteration, the value of "i" will be displayed in the terminal window. The loop will terminate once "i" has iterated over the entire list of numbers.
for i in 1 2 3 4 5; do echo $i; done
The variable i is incremented by one with each iteration of the loop. This is because the list of numbers increases by one each time. The sequence of numbers begins at 3 and continues in increments of two until it jumps to 44 unexpectedly.
for i in 3 5 7 9 11 44; do echo $i; done
The for loop remains unaffected and operates in the same manner. It initiates from one end of the list and sequentially utilizes each value, regardless of their order, until all values within the list have been utilized.
for i in 3 43 44 11 9; do echo $i; done
for Loops Using Word Lists
We can just as easily do the same with words. Copy the text of the script into an editor and save it as "word-list.sh."
#!/bin/bash
for word in "This is a sequence of words"
do
echo $word
done
To make the script executable, use chmod. Make sure to substitute the script's name accordingly whenever using the chmod command for any script copied from this article.
chmod +x word-list.sh
Let's run the script.
/word-list.sh
Similar to the numerical data, the iterator, represented by the variable word in this case, traverses the data items within the list until it reaches the end. Within the body of the loop, the value stored in the word variable is accessed, allowing each word in the list to be processed.
for Loops with Number Ranges
To avoid the arduous task of manually inputting a sequence of 100 numbers in the loop header, one can use number ranges. These ranges allow you to specify only the first and last number, making the process much more efficient.
This script is "number-range.sh."
#!/bin/bashfor i in {1..10}do echo "Loop spin:" $idone
The number range is specified using curly brackets "{}", with two periods ".." separating the starting and ending numbers of the range. Ensure that there are no spaces included in the range definition. Here is an example of how it operates:
/number-range.sh
You have the option to add another number that specifies the increment the iterator should use to iterate through the range of numbers. The script named "number-range2.sh" will iterate through a range from 0 to 32 with an increment of 4.
#!/bin/bash
for i in {0..32..4}
do
echo "Loop iteration:" $i
done
The iterator steps through the number range in jumps of four.
/number-range2.sh
for Loops Using Filenames
As we have the capability to handle word lists, we are able to incorporate filenames in our scripts. The script we are referring to is named "filenames.sh."
#!/bin/bashfor file in word-list.sh number-range.sh number-range2.sh filenames.shdo ls -lh "$file"done
It would be pretty pointless to have a script that only does what ls can do, but it does demonstrate how to access filenames inside the loop body.
/filenames.sh
Instead of manually typing out specific file names, we can simplify the process by using a file pattern in the loop header. This allows us to specify the files we want to process without having to know their names in advance.
The script named "filenames2.sh" has been modified to include a filename pattern of "*.sh" instead of a specific list of filenames. This alteration allows the script to provide information on all script files in the current directory.
#!/bin/bash
for file in *.sh
do
ls -lh "$file"
done
Here's the output.
/filenames2.sh
for Loops Using Command Line Parameters
We can add some more flexibility by passing in the filename pattern on the command line. The $* variable represents all of the command line parameters passed to the script.
This is "filenames3.sh."
#!/bin/bashfor file in $*do ls -lh "$file"done
We'll ask for filenames that begin with "n" and have an SH extension.
/filenames3.sh n*.sh
We can also pass in more than one pattern at a time.
/filenames3.sh n*.sh .bashrc
The iterator variable file takes on the value of each of the command line parameters. Filename patterns are expanded, and all of the filenames are processed in the loop body.
C-like for Loops
The classic three-term for loop, which is commonly used in the C programming language, is also supported by Bash. These loops are named three-term for loops due to the presence of three terms in their loop header.
The initial value of the loop iterator.
The test for whether the loop continues or ends.
The incrementing---or decrementing---of the iterator.
This script is "c-like.sh."
The iterator starts at 1 and continues increasing by one with each iteration of the loop. The loop will continue as long as the value of 'i' is less than or equal to 10. Once 'i' reaches 11, the loop will stop.
Let's run this script.
/c-like.sh
The C-like for loop permits the easy creation of for loops that have slightly odd requirements. This loop starts at 15, and counts backward in steps of 3. This is "c-like2.sh"
#!/bin/bashfor (( i=15; i>0; i-=3 ))do echo "Loop number:" $idone
When we run it, it should jump backward in steps of three.
/c-like2.sh
Infinite for Loops
You can also use this format of for loop to create an infinite loop. All you need do is remove all of the elements from the loop header, like this. This is "infinite.sh."
#!/bin/bashfor (( ; ; ))do echo "Press Ctrl+C to stop..." sleep 1done
You'll need to hit Ctrl+C to stop the loop.
/infinite.sh
for Loops Using Word Arrays
Iterating through an array of words is a straightforward process. In order to do this, we simply need to specify the name of the array in the loop header. The iterator will then sequentially go through each entry in the array. This functionality is implemented in the script "word-array.sh."
#!/bin/bashdistributions=("Ubuntu Fedora Manjaro Arch EndeavourOS Garuda")for distro in $distributionsdo echo $distrodone
All the distributions are listed for us.
/word-array.sh
The continue Command
In order to have the loop skip a specific entry, you can check if the iterator matches that entry and use the continue command. By utilizing the continue command, the current iteration of the loop is abandoned. The iterator is incremented and the next iteration of the loop begins—provided that the entry you wish to skip is not the last item in the list.
This is the script "word-array2.sh." It skips the "Arch" entry in the "distributions" array but processes all the other array members.
#!/bin/bash
distributions=("Ubuntu Fedora Manjaro Arch EndeavourOS Garuda")
for distro in $distributions
do
if [[ "$distro" == "Arch" ]];
then
continue
fi
echo $distro
done
"Arch" doesn't appear in the terminal window.
/word-array2.sh
The break Command
The break command breaks out of the loop and prevents any more processing.
This is "word-array3.sh." It's the same as the previous script with continue replaced by break.
#!/bin/bash
distributions=("Ubuntu" "Fedora" "Manjaro" "Arch" "EndeavourOS" "Garuda")
for distro in "${distributions[@]}"
do
if [[ "$distro" == "Arch" ]]; then
break
fi
echo "$distro"
done
/word-array3.sh
for Loops Using Associative Arrays
In Bash 4 and above, associative arrays enable the creation of collections of key-value pairs that can be searched by either the key or the value. These collections are also known as data dictionaries due to the bi-directional relationship between the key and the value.
We can use a for loop to iterate through an associative array in this script called "associative.sh." It defines an associative array called "animals" with four entries: "dog," "cat," "robin," and "human." These entries represent the keys, while the values represent the default number of legs each animal has.
#!/bin/bash
declare -A animals=(
[dog]=Four-legged
[cat]=Four-legged
[robin]=Two-legged
[human]=Two-legged
)
for legs in ${!animals[@]}
do
if [ ${animals[$legs]} == "Two-legged" ]; then
echo ${legs}
fi
done
The iterator is named legs. Please note that the exclamation point "!" in the loop header is not functioning as the logical NOT operator but is part of the associative array syntax. It is necessary for searching through the array.
Inside the loop, a string comparison test is carried out. If the value of the array element is "Two-legged", the corresponding key value is printed to the terminal window. When executed, the script displays the creatures with two legs.
/associative.sh
Iterating Over the output of Commands
In the event that you possess a command or a series of commands that generate a list of items, such as filenames, it is possible to traverse through them using a for loop. It is important to be cautious of any unexpected expansions of filenames. However, in straightforward scenarios, it should not pose any issues.
The following script, named "command.sh", utilizes the commands ls and wc to generate a sorted list of script file names along with their corresponding line, word, and byte counts.
#!/bin/bash
for i in $(ls *.sh | sort);
do
echo $(wc $i)
done
When we run it we get the statistics for each file, with the files listed in alphabetical order.
/command.sh
The Dazzling for Loop
The for loop is a powerful and intuitive scripting tool. However, it's important to remember that there are other loop options available for specific purposes. Don't overlook the value of the while loop, which can be more suitable for tasks like reading lines from a file.
Writing good scripts means using the most suitable tool for the task at hand. The for loop is a great tool to have in your toolbox of tricks.
Editor's P/S
As a Gen Z netizen, I find the Bash for loop to be an incredibly useful tool for automating tasks and iterating over data. The versatility of the for loop, which allows it to work with numbers, words, arrays, command line variables, and the output of other commands, makes it a powerful tool for a wide range of scripting tasks.
The examples provided in the article are particularly helpful in demonstrating the different ways in which the for loop can be used. From simple numerical and word lists to number ranges, filenames, and command line parameters, the for loop can be used to automate repetitive tasks and process data efficiently.
Overall, I believe that the Bash for loop is an essential tool for any Linux user or system administrator, and I am excited to continue learning and exploring its many uses.