This is a continuation article in bash loop wherein the previous article we have explained about for loop. In this article, we will take a look at two more bash loops namely, while and until loop.
The while loop is mostly used when you have to read the contents of the file and further process it. Reading and writing to a file are common operations when you write bash scripts. We will see how to read files using a while loop.
We already have a very detailed article on how to write to a file using redirection operators.
The functionality of the while loop is similar to for loop. The for loop iterates over a list of items and runs the block of code N a number of times. Here in the while loop, the condition is evaluated first, and if the condition is true, the block of code will be executed until the condition is evaluated to false.
Table of Contents
1. While loop
Below is the while loop syntax. The loop starts with the "while" keyword followed by a condition that should be evaluated to be true. Between do and done block is where your codes will be placed that will be iterated N number of times.
while [[ condition ]] do Command 1 Command 2 .... Command 3 done
EXAMPLE 1 - Evaluate and iterate
Take a look at the below example. Here I have created a variable "NUM=5" and my condition ($NUM -ne 0) is, the loop will execute if the variable NUM is not equal to zero.
$ NUM=5 while [[ $NUM -ne 0 ]] do printf "Value of NUM = $NUM \n" ((--NUM)) done
You should use counters to increment or decrement values stored in variables when working with while loops. If not, it will become an infinite loop and NUM will always be set to five. Here I am decrementing the value of NUM in every iteration by running ((--NUM)), so when my variable NUM is set to zero, the loop exit.
((++NUM)) → Increment NUM variable by 1, similar to running NUM=$(( $NUM + 1 )) ((--NUM)) → Decrement NUM variable by 1, similar to running NUM=$(( $NUM - 1 ))
EXAMPLE 2 - Infinite loops
An infinite loop is where your condition is always evaluated to true and the loop will never exit.
To create infinite loops, you can use the bash-builtin true keyword. Also, use the "sleep" command when testing infinite loops which will give you control in stopping the script else your screen will be flooded with fast scrolling outputs.
$ NUM=0 while true do printf "Value of NUM = $NUM \n" ((++NUM)) sleep 2 done
EXAMPLE 3 - Internal field separator (IFS)
IFS is a special shell variable that decides how your word boundaries are handled. By default, IFS is set to space, tab, and a newline character. Open the terminal and run the following commands:
$ var1="foo:bar foo bar"
$ for val in $var1 do echo $val done
Take a look at the output. The for loop is iterating over a string and it is IFS which decides the word boundaries and considers space as a field separator.
Now run the below code again. Here IFS is set to the colon.
$ var1="foo:bar foo bar"
$ IFS=":"
$ for val in $var1 do echo $val done
From the above output, you can see that the custom field separator colon is used as a word boundary. You can set the IFS back to the default state by running the unset command.
$ unset IFS
EXAMPLE 4 - Read file using while loop
The while loop is recommended when you want to read a file line by line and process it.
Create a new file called test.txt using the following content. There is an empty line after line 2 to show the behavior of how empty lines are handled.
14:00 Brighton v Leicester 14:00 West Ham v Man Utd 16:30 Spurs v Chelsea
We will use the read command which accepts input from redirection and store it in a variable along with an input redirection operator where the file name will be redirected to the while loop. The read command will use the default IFS to set the word split boundary.
$ while read line do echo $line done < test.txt
In the above example, test.txt file is redirected to the while loop and read command reads line by line and stores it in the variable "line" and it is further processed within the loop. Empty lines are not skipped when you follow this method and this is not the behavior you might want. So you have to explicitly make empty lines to be skipped.
There are multiple options to trim out empty lines from the input file. You can use sed, awk, and conditional statements, etc. I prefer using both awk and sed to clean up the empty lines before looping them using a while loop.
# USING SED $ sed -i '/^[[:space:]]*$/d' test.txt 14:00 Brighton v Leicester 14:00 West Ham v Man Utd 16:30 Spurs v Chelsea
# USING AWK $ awk 'NF' test.txt
As seen in previous examples, you can modify IFS depending upon how you want to read your file. For example, if you are handling a CSV file then the delimiter can be set to a comma. I have modified the same input file to be in CSV format.
14:00,Brighton,Leicester 14:00,West Ham,Man Utd 16:30,Spurs,Chelsea
In the below example, IFS is set to comma (IFS=",") and each field will be stored in a separate variable (time, team1, team2).
while IFS="," read time team1 team2 do echo "$team1 is playing against $team2 at $time" done < test.txt
EXAMPLE 5 - Loop flow control with Break and Continue
If you have read our bash for loop article, you might know what is break and continue used for. Both break and continue are bash builtin keywords that will help you to control the flow of your loop.
The "break" keyword will completely exit the loop and pass control to the next command in the script. In the below example. When the NUM is equal to three, the loop will be exited by the break command.
$ NUM=5
while [[ $NUM -ne 0 ]]
do
printf "Value of NUM = $NUM \n"
if [[ $NUM -eq 3 ]]
then
break
fi
((--NUM))
doneThe "continue" keyword will skip the current iteration and give the control back to the while loop and start the next iteration.
$ NUM=0 while [[ $NUM -lt 5 ]] do ((++NUM)) if [[ $NUM -eq 3 ]] then continue fi printf "Value of NUM = $NUM \n" done
2. Until Loop
The until loop is the exact opposite of the while loop. The while loop evaluates the condition to be true to execute the block of code and the until loop evaluates the condition to be false for the loop to be executed.
The syntax is the same as the while loop but instead of the keyword while, until will be used.
until [[ condition ]] do Command 1 Command 2 .... Command 3 done
From the below example, you can see until loop evaluates the variable NUM to be greater than equal to five. It is false since NUM is set to zero and will increment in subsequent iterations using ((++NUM)). So when NUM is equal to five the condition is evaluated to be true and until loop will stop executing.
$ NUM=0
$ until [[ $NUM -ge 5 ]] do echo $NUM ((++NUM)) done
To create infinite loops, you can use the keyword "false".
$ NUM=0
$ until false do echo $NUM ((++NUM)) done
To control the loop flow, you can use the break and continue keywords like as shown in the while loop section above.
Conclusion
In this article, we have seen how to use while loop and until loop in bash scripts. Until loop is least frequently used compared to for and while loops but that is to decide on your script and what types of the loop are required. Be comfortable in using all three loops.
If you've any questions or feedback, feel free to let us know via the comment section below.
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
- How To Repeat A Command Until It Succeeds In Linux
- Difference Between Defining Bash Variables With And Without export










