Bash For Loops - The Most Practical Guide

Bash For Loop – The Most Practical Guide

This article continues the Bash article series and focuses on iterations. Loops in Bash are handy for any system administrator and programmer. Looping constructs in any scripting language allow you to run multiple commands and keep re-running until a specific situation is reached. In simple terms, loops are useful for automating repetitive tasks. There are three loop constructs in a shell scripting language:

  • While-loop.
  • For-loop.
  • Until-loop.

for-loop is an iteration statement in Bash language used to perform a set of actions. You can use it on a shell prompt or within a shell script itself. It operates on lists of items and repeats a set of commands for every item in the list.

Basic Syntax

For loop syntax
For loop syntax

The basic syntax is shown below:

for item in [LIST]
do
  COMMANDS
done

Where:

  • LIST is a series of strings or numbers separated by spaces.
  • COMMANDS is a set of commands that executes over a list of items.
  • forindo, and done are loop syntax keywords.
  • item is a Bash variable name used to get access to the item from the list.

Iterating over numbers

Iterate over numbers (Bash example)

You can use this type of loop to iterate through a series of numbers or numeric list until the list is exhausted.

In the following example, we iterate through numbers 1 2 3 4 5.

#!/bin/bash
for var in 1 2 3 4 5
do
 echo "Number is $var"
done

You should get the following output:

Number is 1
Number is 2
Number is 3
Number is 4
Number is 5

In the above example, for-loop takes each item from the list, stores them in the variable var, and executes the commands between do and done.

You can also specify a range of numbers by defining the range of values.

Iterating over range (Bash example)
Iterating over range (Bash example)

In the following example, we iterate through all numbers between 10 and 15.

#!/bin/bash
for var in {10..15}
do
 echo "Number is $var"
done

You should get the following output:

Number is 10
Number is 11
Number is 12
Number is 13
Number is 14
Number is 15

When you use a specific range within the loop, you can also specify an increment to increment each number.

Iterating with increment (Bash example)
Iterating with increment (Bash example)

In the following example, we iterate through a range of numbers from 0 to 10 and increment each number by 2:

#!/bin/bash
for var in {0..10..2}
do
 echo "Number is $var"
done

You should get the following output:

Number is 0
Number is 2
Number is 4
Number is 6
Number is 8
Number is 10

Iterating over strings

Iterating over strings (Bash example)
Iterating over strings (Bash example)

You can also use loops to iterate over a list of strings.

In the following example, we iterate through a list of strings one by one:

#!/bin/bash
for month in Jan Feb Mar Apr May Jun
do
 echo "Month is $month"
done

You should get the following output:

Month is Jan
Month is Feb
Month is Mar
Month is Apr
Month is May
Month is Jun

Iterating over an array

Iterating over array (Bash example)
Iterating over array (Bash example)

In the following example, we iterate through all elements in the CARS array:

#!/bin/bash
CARS=('Maruti' 'Toyota' 'BMW' 'Tata' 'Datsun')
for car in "${CARS[@]}"; do
  echo "Car: $car"
done

You should get the following output:

Car: Maruti
Car: Toyota
Car: BMW
Car: Tata
Car: Datsun
Iterating with index (Bash example)

In the following example, for-loops iterates all elements in a weekday array.

#!/bin/bash
i=1
weekdays="Mon Tue Wed Thu Fri"
for day in $weekdays
do
 echo "Weekday $((i++)): $day"
done

You should get the following output:

Weekday 1: Mon
Weekday 2: Tue
Weekday 3: Wed
Weekday 4: Thu
Weekday 5: Fri

Infinite loops

You can create an infinite loop using the empty expressions.

#!/bin/bash
for (( ; ; ))
do
   echo "Infinite Loops [ press CTRL+C to stop]"
done

You should get the following output:

Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]
Infinite Loops [ press CTRL+C to stop]

You can press CRTL+C to stop the infinite loop.

Break statement

You can use the break statement to exit from the loop earlier.

In the following example, we iterate through numbers between 20 to 30. We will use if-statement to exit from the loop once the current iterated item is equal to 27.

#!/bin/bash
for var in {20..30}
do
  if [[ "$var" == '27' ]]; then
    break
  fi
  echo "Number is: $var"
done

You should get the following output:

Number is: 20
Number is: 21
Number is: 22
Number is: 23
Number is: 24
Number is: 25
Number is: 26

Continue statement

The continue statement is used inside loops. When a continue statement is encountered inside a loop, the control flow jumps to the beginning of the loop for the next iteration, skipping the execution of statements inside the body of the loop for the current iteration.

In the following example, we iterate through numbers between 10 to 15. When the current iterated item is equal to 13, the continue statement will stop the execution, return to the beginning of the loop and continue with the next iteration:

#!/bin/bash
for var in {10..15}
do
  if [[ "$var" == '13' ]]; then
    continue
  fi
  echo "Number is: $var"
done

You should get the following output:

Number is: 10
Number is: 11
Number is: 12
Number is: 14
Number is: 15

Advance examples

Rename File Extension

This section will show you how to change the extension of all files in the directory.

The following example will change the extension of all files in the current directory from .php to .html.

#!/bin/bash
for file in *.php; do
  mv "$file" "${file%.php}.html"
  echo $file is renamed to "${file%.php}.html"
done

You should get the following output:

admin.php is converted to admin.html
ajax.php is converted to ajax.html
composer.php is converted to composer.html
index.php is converted to index.html
login.php is converted to login.html

Display Number of Times in a Row

In this example, we will display the current system time every 2 seconds.

#!/bin/bash
for now in {1..5}
do
  date
  sleep 2
done

You should get the following output:

Fri Dec  4 12:19:10 IST 2020
Fri Dec  4 12:19:12 IST 2020
Fri Dec  4 12:19:14 IST 2020
Fri Dec  4 12:19:16 IST 2020
Fri Dec  4 12:19:18 IST 2020

Untar Multiple Tar Files

You can perform the same action across all files with the same extension. For example, let’s untar multiple files in the directory.

The following example will extract all tar files located inside the current directory:

#!/bin/bash
for var in *.tar
do
  echo "Processing $var..."
  tar -xf "$var"
done

Ping Multiple Servers

You can use loop expression to ping several servers from the list.

First, create a file named domain.txt and add all servers to this file, as shown below:

cat domain.txt

Add the following lines:

google.com
facebook.com
yahoo.com
wordpress.com

Now, let’s ping all servers listed in the domain.txt file as shown below:

#!/bin/bash
for var in $(cat domain.txt)
do
  ping -c 1 "$var"
done

You should get the following output:

PING google.com (216.58.203.14) 56(84) bytes of data.
64 bytes from hkg12s09-in-f14.1e100.net (216.58.203.14): icmp_seq=1 ttl=117 time=119 ms
 
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 119.469/119.469/119.469/0.000 ms
PING facebook.com (69.171.250.35) 56(84) bytes of data.
64 bytes from edge-star-mini-shv-01-any2.facebook.com (69.171.250.35): icmp_seq=1 ttl=56 time=43.9 ms
 
--- facebook.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 43.994/43.994/43.994/0.000 ms
PING yahoo.com (74.6.231.21) 56(84) bytes of data.
64 bytes from media-router-fp74.prod.media.vip.ne1.yahoo.com (74.6.231.21): icmp_seq=1 ttl=51 time=371 ms
 
--- yahoo.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 371.135/371.135/371.135/0.000 ms
PING wordpress.com (192.0.78.9) 56(84) bytes of data.
64 bytes from 192.0.78.9: icmp_seq=1 ttl=56 time=40.1 ms
 
--- wordpress.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 40.162/40.162/40.162/0.000 ms

List Files with Conditions

Here’s an example showing how to list all files inside a specific directory that are matching specific conditions.

For example, list all .conf files inside /etc directory that begins with either abc or d letters:

#!/bin/bash
i=1
for file in /etc/[abcd]*.conf
do
  echo "File $((i++)) : $file"
done

You should get the list of all files in the following output:

File 1 : /etc/adduser.conf
File 2 : /etc/apg.conf
File 3 : /etc/blkid.conf
File 4 : /etc/brltty.conf
File 5 : /etc/ca-certificates.conf
File 6 : /etc/colord.conf
File 7 : /etc/debconf.conf
File 8 : /etc/deluser.conf

Summary

In this article, we’ve covered various examples of using Bash for-loops. We hope, that now you have an idea of how you can automate your own day to day tasks. If the article was helpful, please, help us to spread it to the world.