How to use for/while/until loop in bash

Last updated on February 13, 2021 by Dan Nanni

Undoubtedly the most useful feature of bash scripting is loop control. In any imperative programming language like bash, loop statements are commonly used along with conditional statements to perform repetitive tasks. In case of bash, three different types of loop statements are available: for, while and until. Each of these loop statements comes in handy in slightly different circumstances.

In this tutorial, I explain how to use for, while and until loops in bash shell scripts, and demonstrate their use cases using shell script examples.

Loop Statements: for vs. while vs. until

Both the for and while statements allow you to express a loop with a terminating condition (i.e., run the loop while the condition is true). The for statement is more versatile than the while statement as you can also iterate over a list of items using a for loop without explicitly defining a condition. Thus for loops are often used when the number of loop iterations or the items to iterate over are already known.

Similar to for and while, the until statement allows you to define a conditional loop. However, the difference of until lies in how the condition is handled. The for/while loops are executed while the condition is true. On the other hand, until loops are iterated until the condition is true, meaning that the loops are executed while the condition is false.

With these key differences in mind, let's go over the syntax and examples of for, while and until loops in the following.

for Loops in bash

The for Loop Syntax

The most commonly used form of for loops is a single-expression loop as shown below. The loop body surrounded by do and done is executed as long as <conditional-expression> evaluates to true. <conditional-expression> can be written in many different forms, some of which will be illustrated with examples later.

for <conditional-expression>
do
    <loop-body>
done
for <conditional-expression>; do
    <loop-body>
done

Another form of for loops is a three-expression loop as shown below. The control flow in this loop is as follows. First, <init-expression> is executed once before the loop starts. Then <conditional-expression> is evaluated. If the condition evaluates to true, the loop is entered and the loop body is executed. After the loop body is completed, the control flow jumps back to <update-expression>, where any loop control variable can be updated. Then <conditional-expression> is evaluated again. If true, loop iteration continues, and the whole process repeats itself.

Note that there should be spaces between opening/closing double round brackets and the init/update expressions.

for (( <init-expression>; <conditional-expression>; <update-expression> )); do
    <loop-body>
done

Example #1: Repeat N Times or Iterate over a Range in for Loop in bash

To repeat N times, where N is a variable, use either of the following formats.

N=10
for i in $(seq 1 $N); do
  echo "$i-th run"
done
N=10
for (( i=0; i <= $N ; i++ )); do
    echo "$i-th run"
done

To iterate over a fixed range of values, specify the range with {START..END} in the conditional expression.

# iterate all integers from 10 to 100
for i in {10..100}; do
    echo "count $i"
done

To iterate over a range of values with a fixed increment, use {START..END..INCREMENT} in the conditional expression.

# iterate over 10, 15, 20, ..., 95, 100 
for i in {10..100..5}; do
    echo "count $i"
done

The above for loop can of course be re-written easily with a three-expression loop.

for (( i=0; i <= 100 ; i=i+5 )); do
    echo "count $i"
done

Example #2: Iterate over a List of Strings in for Loop in bash

fruit_list=('apple' 'orange' 'kiwi' 'pear' 'watermelon')
for fruit in "${fruit_list[@]}"; do
    echo $fruit
done
fruit_list="apple orange kiwi pear watermelon"
for fruit in $fruit_list; do
    echo $fruit
done
for fruit in apple orange kiwi pear watermelon; do
    echo $fruit
done

while Loop in bash

The while Loop Syntax

A while loop in bash consists of a conditional expression and a loop body which is surrounded by do and done. The loop body continues to be executed as long as the condition evaluates to true. The conditional expression in while loop can be surrounded by either a pair of single square brackets or a pair of double round brackets. Depending on whether you are using square brackets or round brackets, the type of operators you are allowed to use vary, as illustrated below. Also note that there should be spaces between opening/closing brackets and the conditional-expression.

while [ <conditional-expression> ]; do
    <loop-body>
done
while (( <conditional-expression> )); do
    <loop-body>
done

Example #1: Integer Comparison in while Loop in bash

In a while loop, integer comparison inside the square brackets should be expressed using bash's built-in comparison operators (-eq for "equal to", -ne for "not equal to", -gt for "greater than", -ge for "greater than or equal to", -lt for "less than", -le for "less than or equal to").

i=0
while [ $i -lt 100 ]; do
    i=`expr $i + 1`
    echo $i
done

If you are using double round brackets, you can use '>', '<', '==', '!=', '>=', '<=' operators for integer comparison in while loop.

i=0
while (( $i < 100 )); do
    i=`expr $i + 1`
    echo $i
done

Example #2: String Comparison in while Loop in bash

For string comparison (equal or not equal), you can use regular comparison operators ('==', '!='), whether you are using square brackets or double round brackets. The '=' operator can also be used to check equality of strings.

TIME=`date +%H:%I`
while [ "$TIME" != "00:00" ]; do
    # do something
    HOUR=`date +%H:%I`
done
TIME=`date +%H:%I`
while (( "$TIME" == "00:00" )); do
    # do something
    HOUR=`date +%H:%I`
done
while (( "$TIME" = "00:00" )); do
    # do something
    HOUR=`date +%H:%I`
done

Example #3: Multiple Conditions in while Loop

When you want to specify multiple conditions with logical AND/OR, you can do that in several different ways.

Combine multiple pairs of square brackets using '&&', '||' operators:

MIN=`date +%M`
while [ "$MIN" -gt 0 ] && [ "$MIN" -lt 30 ] ; do
    # do something
    MIN=`date +%M`
done

Use a single pair of square brackets and use bash's built-in logical operators (-a for AND, -o for OR):

MIN=`date +%M`
while [ "$MIN" -gt 0 -a "$MIN" -lt 30 ] ; do
    # do something
    MIN=`date +%M`
done

Use a single pair of double round brackets and use '&&' and '||' operators.

MIN=`date +%M`
while (( "$MIN" > 0 && "$MIN" < 30 )); do
    # do something
    MIN=`date +%M`
done

until Loop in bash

The until Loop Syntax

The syntax of until loops is identical to that of while loops. But contrary to while loops, the loop body in until loops continues to be executed only if <conditional-expression> evaluates to false. As soon as <conditional-expression> evaluates to true, the loop is exited.

Similar to while loops, the conditional expression in until loops can be surrounded by either a pair of single square brackets or a pair of double round brackets. The type of comparison operators you are allowed to use inside the brackets vary depending on whether you are using square brackets or round brackets. There should be spaces between opening/closing brackets and the conditional-expression.

until [ <conditional-expression> ]; do
    <loop-body>
done
until (( <conditional-expression> )); do
    <loop-body>
done

Example #1:

The semantic difference between while and until can be illustrated with the following two shell scripts. They produce exactly the same result.

i=0
while [ $i -lt 100 ]; do
    i=`expr $i + 1`
    echo $i
done
i=0
until [ $i -ge 100 ]; do
    i=`expr $i + 1`
    echo $i
done

For other until loop examples such as integer comparison, string comparison and multiple conditions, refer to those demonstrated in the while loop.

If you find this tutorial helpful, I recommend you check out the series of bash shell scripting tutorials provided by Xmodulo.

Support Xmodulo

This website is made possible by minimal ads and your gracious donation via PayPal (Credit Card) or Bitcoin (1M161JGAkz3oaHNvTiPFjNYkeABox8rb4g).

Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.

Xmodulo © 2021 ‒ AboutWrite for UsFeed ‒ Powered by DigitalOcean