In Bash shell scripting, Loops are useful for automating repetitive tasks. When you have to repeat a task N number of times in your script, loops should be used. There are three types of loops supported in bash.
- For loop
- While loop
- Until loop
All three loops serve the same purpose of repeating the task N number of times when a condition is satisfied but with differences in how they are defined and used to achieve the result.
This article will focus on "for loop" in Bash scripting. We will learn about the other two loops in our next guide.
For loop syntax
Understanding syntax is very important before you write your first for loop
.
for NAME in [ LIST OF ITEMS ] do Command 1 Command 2 ..... Command N done
Let's break it down and see what it does.
- Start with the keyword
"for"
followed by a variable name. - The keyword
"in"
get the list of items and store it in the variable for each iteration. - The keyword
"do"
and"done"
marks the start and end of the loop block and the command should be written within do and done. - There are no strict indentation rules but for better readability use 2 spaces or tab(4). Be consistent in using either space or tab throughout your script.
You can also create a single line for loops. Create a for loop
in the terminal and press the up arrow key and you will see bash automatically converts it into a single line loop.
for NAME in [ LIST OF ITEMS]; do COMMANDS ; done
Example 1 - Working with list of items
Let’s start with a simple example.
From the previous section, you might have understood that the for loop
accepts a list of items. The list of items can be anything like strings, arrays, integers, ranges, command output, etc.
Open the terminal and run the following piece of code.
N=1 for val in Welcome To Ostechnix do echo "Iteration $N → $val" ((++N)) done
Let's break it down.
"Welcome to Ostechnix"
is the list of items passed to thefor loop
and each word will be picked as a separate iteration and stored in a variable (val
).- The variable can be named anything. Here I name it as
val
. - There are three items in the list so there will be three iterations in the
for loop
and each time the value of variableval
is printed. - The command ((
++N
)) will act as a counter and increment the variable valueN
so it can be printed in theecho
statement.
Now after running the above for loop
command press the up arrow key from the terminal and you can see the multi-line for loop
is converted to a single line for a loop.
Example 2 - Working with ranges
You may want to run the for loop
N number of times, for that, you can use bash built-in sequence generator "{x..y[..incr]}"
which will generate a sequence of numbers.
X
= Starting Integer valueY
= Ending Integer valueIncr
= optional Integer value which does increment of integers
Let’s say you want to run for loop five times then you can use the following snippet.
for rng in {1..5} do echo "Value is == $rng" done
You can also use the optional increment parameter which will do step-wise increments.
Take a look at the below snippet where the increment of three is given. This will generate the sequence from one and do a step increment of three until the end value ten.
for rng1 in {1..10..3} do echo "Value is == $rng1" done
Example 3 - Running commands
You can run any commands that derive a list of items to be processed by for loop
. The command should be either enclosed with ticks "``
" or brackets "$()
".
In the below example, I am running the command that will get process ID and filter the last five processes. For loop will now iterate through each process ID.
for list in $(ps -ef | awk {' print $2 '} | tail -n 5) do echo $list done
Example 4 - Loop over array elements
In real-time scenarios, you will store some values in arrays and try to loop over the array for further processing.
Before understanding how to iterate through an array, you have to understand the behavior of two special variables( $@
and $*
). Both these are special variables that are used to access all the elements from an array.
Run the following piece of code in the terminal. An array X is created and when I try to print all the values ($X
) like how I print variables, it is just returning the first value from the array.
$ X=( 16 09 2021 "Thursday Third Week" )
$ echo $X
16
To access all the elements in an array, you either have to use $@
or $*
. The syntax for accessing array values will be as follows.
$ echo ${X[@]}
16 09 2021 Thursday Third Week
$ echo ${X[*]}
16 09 2021 Thursday Third Week
Now use this with for loop
to iterate through the array values.
X=( 16 09 2021 "Thursday Third Week" ) for items in ${X[@]} do echo $items done
Take a look at the above output. This output seems to be wrong, because the string (Thursday Third Week) inside the array should be considered as a single value. But here each item is treated as a separate item.
This is the default behavior when you use $@
or $
. To overcome this, enclose the array expansion variable ($@
or $
) in double-quotes.
for items in "${X[@]}" do echo $items done
When you use double quotes, $@
and $*
behave differently. While $@
expands the array to each item in an array-like as shown in the above example, $*
will expand the entire array as one value.
for items in "${X[*]}" do echo $items done
Heads Up: Both $@
and $*
behave identically unless it is enclosed with double-quotes. Try to avoid $*
unless it is needed.
Example 5 - C style for loop syntax
Bash also offers c style for loop
syntax. If are from a C language background, then this syntax will not be new to you.
Instead of iterating through a list, you will be evaluating a condition and if the condition is true, the commands within the loop will be executed.
There are three parameters that you have to understand in this syntax.
- Variable - A variable is initialized only once when the loop is triggered.
- Condition - Condition should be true for the loop to be executed else the loop will not run.
- Counter - This will increment the variable value.
Each parameter should be separated by a semicolon (;
) and should be enclosed in double brackets as shown below.
for (( variable; condition; counter )) do Command 1 Command 2 Command N done
Take a look at the below leap year example.
- The variable
YEAR=2010
will be first initialized. - The condition
YEAR<=20
will be evaluated and if it is true the code betweendo
and thedone
block will be executed. - The counter
YEAR++
will increment the year by one count. Till the variableYEAR
is incremented to2020
, the loop will iterate. - Within
do
anddone
block, conditional statement is written to check if the year is a leap year or not.
for ((YEAR=2010; YEAR<=2020; YEAR++)) do if [[ $(expr $YEAR % 4) -eq 0 ]] then echo "$YEAR = leap year" else echo "$YEAR = not a leap year" fi done
Example 6 - Break, Continue statement usage
There are two bash built-in keywords that are used to control the flow of your loops.
- Break - Exits the loop and skip any pending iterations.
- Continue - Skip the current iteration and pass the control back to the for loop to execute the next iteration.
To check if they are bash built-in or not, use type
command:
$ type break continue break is a shell builtin continue is a shell builtin
Let’s see in brief how and where both break and to continue can be used.
I am using the same code I used in the previous section to find the leap year. In this case, I just need what will be the first leap year between 2010 and 2020. If that year is found, my loop can exit.
for ((YEAR=2010; YEAR<=2020; YEAR++)) do if [[ $(expr $YEAR % 4) -eq 0 ]] then echo "$YEAR = leap year" break else echo "$YEAR = not a leap year" fi done
From the above output, you can see for loop
iterates, and when the first leap year 2012 is found, break
statement is read and the loop is exited and control is given back to the terminal.
Now I am altering the same code for the "continue"
statement. The continue
statement when it is interpreted it will skip the current iteration i.e whatever code that comes after continue statement and pass the control back to for loop
to run the next iteration.
for ((YEAR=2010; YEAR<=2020; YEAR++)) do if [[ $(expr $YEAR % 4) -eq 0 ]] then echo "$YEAR = leap year" else continue echo "$YEAR = not a leap year" fi done
From the above image, you can see there is an echo statement that is skipped by the continue statement.
Example 7 - True statement usage
When you create loops or conditional statements, you cannot leave the block of code empty. Bash will throw a syntax error.
Take a look at both the above images. In the first image, I created a for loop
but no commands between do
and done
. Similarly in the second image, I left the else clause empty. In both cases, bash is not accepting empty blocks and throws syntax errors.
You can use bash builtin “true"
keyword which will be always set the exit code to 0 (success).
$ type true true is a shell builtin
In this way, you are leaving the code block kind of empty without bash throwing any errors.
Conclusion
In this guide, we have started with the introduction to loops and syntax of for loop
along with C style. We have also seen how to use bash for loops in different conditions along with loop control statements break and continue. Check our next guide to learn about Bash While
and Until
loops with examples.
Related read:
- Bash Scripting – Select Loop Explained With Examples
- Bash Scripting – Functions Explained With Examples
- Bash Scripting – Variables Explained With Examples
- Bash Echo Command Explained With Examples In Linux
- Bash Heredoc Tutorial For Beginners
- Bash Redirection Explained With Examples
- Difference Between Defining Bash Variables With And Without export