Bash For Loop

Updated on

6 min read

Bash For Loop

Loops are one of the fundamental concepts of programming languages. They are handy when you want to run a series of commands repeatedly until a specific condition is reached.

In scripting languages like Bash, loops are useful for automating repetitive tasks, eliminating the need to write the same code repeatedly.

There are three basic loop constructs in Bash scripting: for loop, while loop , and until loop .

In this article, we will cover the basics of the for loops in Bash and show you how to use the break and continue statements to alter the flow of a loop.

The Standard Bash for Loop

The for loop iterates over a list of items and performs the given set of commands.

The Bash for loop takes the following form:

for item in [LIST]
do
  [COMMANDS]
done

The list can be a series of strings separated by spaces, a range of numbers, the output of a command, an array, arguments passed from the command line, and so on.

Loop over strings

The example below shows a loop that iterates over a list of strings. The loop operates on each item in the list, and the variable element stores the item that the loop is currently operating on.

for element in Hydrogen Helium Lithium Beryllium
do
  echo "Element: $element"
done

The loop will produce the following output:

Element: Hydrogen
Element: Helium
Element: Lithium
Element: Beryllium

Loop over a range

You can use the sequence expression to specify a range of numbers or characters by defining the start and the end point of the range. The sequence expression takes the following form:

{START..END}

Here is an example loop that iterates through all numbers from 0 to 3:

for i in {0..3}
do
  echo "Number: $i"
done
Number: 0
Number: 1
Number: 2
Number: 3

Starting from Bash 4, it is also possible to specify an increment when using ranges. The expression takes the following form:

{START..END..INCREMENT}

Here’s an example showing how to increment by 5:

for i in {0..20..5}
do
  echo "Number: $i"
done
Number: 0
Number: 5
Number: 10
Number: 15
Number: 20

Loop over array elements

You can also use the for loop to iterate over an array of elements.

In the example below, we define an array named BOOKS and iterate over each element of the array.

BOOKS=('In Search of Lost Time' 'Don Quixote' 'Ulysses' 'The Great Gatsby')

for book in "${BOOKS[@]}"; do
  echo "Book: $book"
done
Book: In Search of Lost Time
Book: Don Quixote
Book: Ulysses
Book: The Great Gatsby

The C-style Bash for loop

The syntax of the C-style for loop takes the following form:

for ((INITIALIZATION; TEST; STEP))
do
  [COMMANDS]
done

The INITIALIZATION part is executed only once when the loop starts. Then, the TEST part is evaluated. If it is false, the loop is terminated. If the TEST is true, commands inside the body of the for loop are executed, and the STEP part is updated.

In the following example code, the loop starts by initializing i = 0, and before each iteration, checks if i ≤ 10. If true, it prints the current value of i and [increments the variable] i by 1 (i++). Otherwise, the loop terminates.

for ((i = 0 ; i <= 1000 ; i++)); do
  echo "Counter: $i"
done

The loop will iterate 1001 times and produce the following output:

Counter: 0
Counter: 1
Counter: 2
...
Counter: 998
Counter: 999
Counter: 1000

Nesting Loops

A nested loop is a loop inside another loop. You can nest any loop for any number of times.

In a nested for loop, the inner loop runs a complete cycle of its iterations for every outer loop iteration. This means that for every execution of the outer loop, the inner loop will execute all of its iterations until the outer loop completes its cycle.

Here’s an example code that copies three files one by one to three servers.

for f in file_{1..3}; do 
  for j in server_{1..3}; do 
    echo "Copying file $f to server $j"; 
    # command to copy files
  done; 
done
Copying file file_1 to server server_1
Copying file file_1 to server server_2
Copying file file_1 to server server_3
Copying file file_2 to server server_1
Copying file file_2 to server server_2
Copying file file_2 to server server_3
Copying file file_3 to server server_1
Copying file file_3 to server server_2
Copying file file_3 to server server_3

break and continue Statements

The break and continue statements can be used to control the for loop execution.

break Statement

The break statement terminates the current loop and passes program control to the statement that follows the terminated statement. It is generally used to terminate the loop when a specific condition is met.

In the following example, we use the if statement to terminate the execution of the loop once the current iterated item is equal to ‘Lithium’.

for element in Hydrogen Helium Lithium Beryllium; do
  if [[ "$element" == 'Lithium' ]]; then
    break
  fi
  echo "Element: $element"
done

echo 'All Done!'
Element: Hydrogen
Element: Helium
All Done!

continue Statement

The continue statement exits the current iteration of a loop and passes program control to the next iteration of the loop.

In the following example, we are iterating through a range of numbers. When the current iterated item is equal to ‘2’, the continue statement will cause execution to return to the beginning of the loop and to continue with the next iteration:

for i in {1..5}; do
  if [[ "$i" == '2' ]]; then
    continue
  fi
  echo "Number: $i"
done
Number: 1
Number: 3
Number: 4
Number: 5

Bash for Loop Examples

Renaming files with spaces in the filename

The following example shows how to rename all of the files in the current directory with a space in its names by replacing the spaces to underscores:

for file in *\ *; do
  mv "$file" "${file// /_}"
done

Let’s break down the code line by line:

  • The first line creates a for loop and iterates through a list of all files with a space in its name. The expression *\ * creates the list.
  • The second line applies to each item of the list and moves the file to a new one, replacing the space with an underscore (_). The part ${file// /_} is using the shell parameter expansion to replace a pattern within a parameter with a string.
  • done indicates the end of the loop segment.

Changing file extension

The following example shows how to use the Bash for loop to rename all files ending with .jpeg in the current directory by replacing the file extension from .jpeg to .jpg.

for file in *.jpeg; do
    mv -- "$file" "${file%.jpeg}.jpg"
done

Let’s analyze the code line by line:

  • The first line creates a for loop and iterates through a list of all files ending with ‘.jpeg’.
  • The second line applies to each item of the list and moves the file to a new one, replacing ‘.jpeg’ with ‘.jpg’. ${file%.jpeg} to remove the ‘.jpeg’ part from the filename using the shell parameter expansion
  • done indicates the end of the loop segment.

Conclusion

The Bash for loop is used to execute a given set of commands repeatedly for a fixed number of times.

If you have any questions or feedback, feel free to leave a comment.