Bash For Loops: Guide to Iteration in Linux
For loops in Bash are vital control structures used in scripting to repeat tasks. They offer the ability to execute a series of commands multiple times, looping over ranges, variables, command outputs, and more.
This comprehensive tutorial will take you through various ways to utilize for loops in Bash.
From basic syntax to more advanced topics like nested loops and dynamic sequence generation.
- 1 Basic Syntax
- 2 Iterating a Sequence of Numbers
- 3 For Loop with Range
- 4 Iterating Over Strings
- 5 Iterating over Command Output
- 6 Looping Over Files and Directories
- 7 Loop Control Statements
- 8 Nested For Loops
- 9 Dynamic Generation of Loop Sequences (using seq)
- 10 Infinite Bash for Loop
- 11 C-Style
- 12 Using $@ & $*
Basic Syntax
A for loop in Bash generally follows this syntax:
for VARIABLE in ELEMENT_1 ELEMENT_2 ... ELEMENT_N do COMMAND1 COMMAND2 ... done
Here, the loop iterates over the elements and performs the commands enclosed between do
and done
.
Now, if you run this simple example:
for i in 1 2 3 do echo $i done
Output:
1 2 3
In this code, the loop iterates three times, setting the variable i
to the values 1, 2, and 3 in each iteration, respectively. It then prints the value of i
, resulting in the above output.
Iterating a Sequence of Numbers
In Linux Bash, you can easily iterate over a sequence of numbers. Here’s how:
for number in {1..5} do echo $number done
Output:
1 2 3 4 5
The loop runs five times, with the variable number
taking the values from 1 to 5 in sequence. The echo
command prints these values one by one, line by line.
For Loop with Range
You can create loops in Bash with a specified range using the syntax {START..END..INCREMENT}
. Here’s an example:
for number in {0..10..2} do echo $number done
Output:
0 2 4 6 8 10
This loop iterates over the numbers from 0 to 10 in increments of 2. The variable number
is assigned these values sequentially, and they are printed line by line.
Iterating Over Strings
Iterating over strings is straightforward in Bash. Here’s an example:
for string in "apple" "banana" "cherry" do echo $string done
Output:
apple banana cherry
Here, the loop iterates three times, each time assigning a different fruit name to the variable string
. Consequently, it prints these fruit names.
Iterating over Command Output
You can iterate over the output of a command in Bash. Here’s how to list all the text files in a directory:
for file in $(ls *.txt) do echo $file done
Output:
file1.txt file2.txt file3.txt
The loop runs the ls *.txt
command and get the names of all text files in the directory.
The variable file
then takes each filename in turn, and the echo
command prints them.
Looping Over Files and Directories
Here’s an example to list all the directories within the current folder:
for dir in */ do echo $dir done
Output:
dir1/ dir2/ dir3/
In this case, the loop iterates over all the directories in the current folder, denoted by the trailing slash */
.
The variable dir
takes the value of each directory name in turn, and the echo
command prints them.
Loop Control Statements
Loop control statements help in controlling the flow within a loop.
break
Terminates the loop. Example:
for number in {1..5} do if [ $number -eq 3 ]; then break fi echo $number done
Output:
1 2
The loop exits when number
equals 3, resulting in only 1 and 2 being printed.
continue
Skips to the next iteration. Example:
for number in {1..5} do if [ $number -eq 3 ]; then continue fi echo $number done
Output:
1 2 4 5
The loop skips printing 3 and continues with the other numbers.
exit
Exits the entire script. Example:
for number in {1..5} do if [ $number -eq 3 ]; then exit fi echo $number done
Output:
1 2
The entire script is terminated when number
equals 3, and no further code is executed.
Nested For Loops
Nested for loops consist of one or more loops within another loop. Here’s an example that uses two nested loops to create a multiplication table:
for i in {1..3} do for j in {1..3} do echo -n "$((i * j)) " done echo done
Output:
1 2 3 2 4 6 3 6 9
Here, the outer loop iterates over the numbers 1 to 3, and the inner loop does the same.
Inside the inner loop, the product of the variables i
and j
is printed, creating a 3×3 multiplication table.
Dynamic Generation of Loop Sequences (using seq)
You can use the seq
command dynamically generate for loops sequences. Here’s an example:
for number in $(seq 1 2 9) do echo $number done
Output:
1 3 5 7 9
Here, the seq 1 2 9
command generates a sequence of numbers from 1 to 9, incrementing by 2.
The loop iterates over these numbers, printing them line by line.
Infinite Bash for Loop
An infinite loop continues indefinitely without a termination condition. Here’s a simple example:
for (( ; ; )) do echo "This is an infinite loop." sleep 1 done
Output:
This is an infinite loop. This is an infinite loop. ...
When to Use Infinite Loops: Infinite loops can be useful for tasks that need to continue without stopping, such as monitoring a system process or waiting for a specific event.
How to Stop It: To stop an infinite loop, you use a termination command like CTRL+C.
Infinite loops must be used with caution, as they can potentially consume system resources if not managed properly.
C-Style
Bash supports C-style for loops, providing a familiar syntax for those familiar with programming in C. Here’s an example:
for (( i=0; i<3; i++ )) do echo "Iteration number $i" done
Output:
Iteration number 0 Iteration number 1 Iteration number 2
This loop begins with i
set to 0 and continues while i
is less than 3, incrementing i
by 1 at each iteration. It prints the iteration number for each value of i
.
Using $@
& $*
In Bash, $@
and $*
are special variables that deal with command-line arguments, and they can be used within loops. Here’s how:
for arg in "$@" do echo $arg done
Output (if script is called with ./script.sh one two three
):
one two three
$@
treats each argument as a separate word, and the loop prints them one by one.
Using $*
:
for arg in "$*" do echo $arg done
Output (if script is called with ./script.sh one two three
):
one two three
$*
treats all arguments as a single string, so the loop prints them on one line.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.
In the last example there is:
for folder in $PATH
How does the script know to look in actual folders. We never used -d to specify we wanted to look in directories.
When we use the asterisk * it means all files and directories in that folder.
So we get files and directories BOTH of them without filtering.
The filtration to get the folders is on the second if statement which is.
for file in $folder/*
Then we search for the executable with -x
Now I get it. Thanks.
For a nearly total noob it is confusing 😛
You are always welcome.
If I understood your question: I think the $PATH global variable only contains a list of folders in which the executables are stored, separated by “:”. To see these folders on your system just type echo $PATH. On my system, it returns the string “/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin”
None of those can be a file, so he didn’t need to filter.
Great comment really.
Thanks for the contribution.
GREAT articles btw! I’m learning SO MUCH!
I started at Linux file system->Main Linux Commands->Main Linux Commands (Part 2) -> Linux Environment Variables -> Linux Command Line Tricks -> Bash Script Step-by-Step ->Bash Scripting Part 2 -> Part 3 where I am currently 🙂
Thanks, and don’t stop delivering!
Great to know that.
I do my best to post quality content.
Hope the community loves it.
Regards.