Bash (Bourne Again Shell) is a shell command prompt and scripting language in GNU/Linux operating systems. It is the default shell for most Linux distributions.

Like most scripting languages, Bash provides loop syntaxes to repeat similar tasks multiple times. In this article, we will learn how to use the for loop in Bash.

Introduction

A typical Bash script contains a series of commands to be executed one after the other. Variables can be used to store strings, integer index values, results of a command, etc. Loops are required when the user wants to execute a particular command multiple times. It is of particular use when the output of one command is in the form of a list, and on each result, in the list, a second command is to be run.

General Syntax

The general syntax for for loop in Bash is:

for <variable> in <range/list>
do
  ...
  ...
done

Here, the <variable> is a Bash variable, which must be a valid Linux shell variable name, i.e., the name contains a combination of letters(a-z, A-Z), numbers (0-9) and underscore ( _ ) and it must start with either a letter or an underscore.

The <range/list> is either a custom range of integer indices that will be looped or a custom list of integers or strings. It can also contain another Linux command, however, the output of such command must be separated by spaces or newline characters, i.e., parsable by Bash into a list (A list in Bash is basically a collection of values separated by a space or a newline).

Whichever command(s) is to be executed must be placed inside the do..done block.

Let us see a few simple examples.

Looping on a range of Integer values: The following code creates directories named dir1, dir2, dir3 upto dir10.

for i in {1..10}
do
  mkdir dir$i
done

Looping on a list of fixed values: The following code prints each string or integer in the given fixed list.

for i in Hello 1 2 3 Bye!
do
  echo $i
done

Looping on output of a command: The following code loops over output of ls and prints name of each file in the given format.

for i in `ls`
do
  echo "Filename is $i"
done

Expression based Syntax

An expression-based syntax similar to C programming language is also possible in Bash:

for ((Expression 1; Expression 2; Expression 3))
do
  ...
  ... 
done

Here, Expression 1 is the initialization of the index variable(s). Expression 2 is the condition when the loop must be exited; this condition is checked in each iteration. Expression 3 specifies the increment/decrement/modification in value of the index variable(s)

Following example simply prints values from 0 to 4:

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

Following example creates an infinite loop, since no expressions are being specified:

for (( ; ; ))
do
  echo "Press Ctrl-C to stop"
done

Break and Continue

Break Statement for Conditional Exit

We can also use the conditional statement if inside the loop. The if statement can be used with a break statement, for a conditional exit from the loop.

for ((i=0;i<10;i++))
do 
  if [[ $i -eq 5 ]] then 
    break 
  else 
    echo $i; 
  fi 
done

The above loop will print numbers from 0 to 4. Then when the value of i is 5, it will break out of the loop. This is of particular use when a loop is to be exited when a command gives a specific output. For example, the following loop breaks if and when it finds an empty file.

for file in `ls`
do 
  flen=`wc -c $file`
  if [[ "$flen" = "0 $file" ]] then 
    echo "$file is empty"
    break
  else
    echo $flen 
  fi
done 

The command wc -c <filename> prints number of lines in the file <filename>. It prints it in the format <no_of_lines> <filename>, for example, 10 test.txt. We are breaking out of the loop when the number of lines are 0, i.e., an empty file.

Continue Statement to Skip an Iteration Conditionally

Similar to C and many other programming languages, bash also has a continue statement, to skip remaining part of an iteration in a loop if a particular condition is satisfied.

for ((i=0;i<10;i++))
do 
  if [[ $i -eq 5 ]] then 
    continue 
  fi
  echo $i;  
done

The above loop will print numbers from 0 to 10, except 5, because during the iteration of i=5 there is a continue statement, which will skip rest of the code in the loop at the start with the iteration of i=6.

In the following example, we print the number of lines in a file, and a particular iteration will continue if it is a directory and not a file.

for file in `ls`
do 
  if [[ -d $file ]] then 
    continue
  fi 
  wc -c "$file"
done

[[ -d $file ]] checks if the file is a directory. If it is, then we skip over to the next file, i.e. next iteration. If it is not a directory, we print the number of lines in the file using wc command, as shown previously as well.

Using Loops: Scripts and Command Line

The loop syntax can be used in Bash shell directly, or from a shell script file. Once a for loop syntax is entered on the shell, the shell continues the prompt to let the user continue the commands to be looped.

Or else the user can save this in a script file and execute the script file.

The #!/bin/bash at the start specifies the interpreter to be used when the file is executed. Although Bash is the most commonly used shell nowadays, some users do prefer shells like zsh, which should be specified in place of bash at the start of this file.

To give execute permissions for this file, run:

chmod +x test.sh

Finally, to execute the file, run:

./test.sh

Conclusion

The for loop in Bash is a pretty simple feature but has its use in almost every kind of complex scripting scenario. Learning it goes a long way whether you are a regular or advanced Linux user, or beginning to learn automation for System Administration and DevOps tasks.