Definitions

Loops are very important when programming, that is the way you can take full advantage of the speed of computers to solve different problems.

Computers are great at doing repetitive task, and they are fast too.

I can still remember when being a child I started coding with Basic (Yes the old Basic), and Do…While, Do…Until and For were some of the most important lessons learned, together with IF statement.

Now, that I use Linux and Mac OSX a lot, I take full advantage of For…Loop. Specially when working with a lot of files at a time.

In computer science we have two main loops: For Loop and While Loop. Just to clarify things, lets look at Wikipedia's definition for each of them:

For Loop:

In computer science a for loop is a programming language statement which allows code to be repeatedly executed. A for loop is classified as an iteration statement. Unlike many other kinds of loops, such as the while loop, the for loop is often distinguished by an explicit loop counter or loop variable. This allows the body of the for loop (the code that is being repeatedly executed) to know about the sequencing of each iteration. For loops are also typically used when the number of iterations is known before entering the loop. For loops are the shorthand way to make loops when the number of iterations is known, as a for loop can be written as a while loop. The name for loop comes from the English word for, which is used as the keyword in most programming languages to introduce a for loop. The loop body is executed "for" the given values of the loop variable, though this is more explicit in the ALGOL version of the statement, in which a list of possible values and/or increments can be specified.

While Loop:

In most computer programming languages, a while loop is a control flow statement that allows code to be executed repeatedly based on a given boolean condition. The while loop can be thought of as a repeating if statement.

With that understood, lets start with Bash for loop article.

How to use bash for loop

When working with Bash we have two ways to implement For loops

  1. Is instructing For to act and a predefined list of elements, with the for … in statement.
  2. Is using C syntax for (( exp1, exp2, exp3 ))

Watch these simple examples of each way.

Using for ... in statement

for i in 1 2 3 4
	do
		echo "Number $i"
	done

Using for ((exp1, exp2, exp3)) statement

for (( i=1; i<=4; i++))
	do
		echo "Number $i"
	done

The result will be the same in both cases, this is the output.

Number 1
Number 2
Number 3
Number 4

Examples

Counting:

#!/bin/bash
for i in {1..25}
do
    echo $i
done

or:

#!/bin/bash
for ((i=1;i<=25;i+=1)
do
    echo $i
done

Counting on "n" steps

#!/bin/bash
for i in {0..25..5}
do
    echo $i
done

That will count with 5 to 5 steps.

Counting backwards

#!/bin/bash
for i {25..0..-5}
do
    echo $i
done

Acting on files

One of the best uses for loop have in Bash is when you are working on files.

for file in ~/*.md
do
	echo $file
done

That example will just list all files with "md" extension. It is the same as ls *.md

Now a nice and useful example. Calculate prime numbers

read -p "How many prime numbers ?: " num

c=0
k=0
n=2

echo 1
numero=$[$num-1]

while [ $k -ne $num ]; do
     for i in `seq 1 $n`;do
        r=$[$n%$i]
                if [ $r -eq 0 ]; then
                        c=$[$c+1]
                fi
     done

      if [ $c -eq 2 ]; then
              echo "$i"
              k=$[$k+1]
        fi
        n=$[$n+1]
        c=0
done

It will ask you how many prime numbers you want, and then will look for those prime numbers. It is using a For Loop, to divide a number between all numbers and find if it is only divisible between 1 and itself.

Break and continue for loop:

Sometimes you may want to break the loop before it actually finish executing, for example, you are looking for a condition to be met, you can check the status of a variable for that condition. Once the contidition is met, you can break the loop. Here is how.

for i in [series]
do
        command 1
        command 2
        command 3
        if (condition) # Condition to break the loop
        then
                command 4 # Command if the loop needs to be broken
                break
    fi
        command 5 # Command to run if the "condition" is never true 
done

With the use of if ... then you can insert a condition, and when it is true, the loop will be broken with the break statement.

Continue the loop:

for i in [series]
do
    command 1
    command 2
    if (condition) # Condition to jump over command 3
            continue # skip to the next value in "series"
    fi
    command 3
done

As you can see they are similar. But with break you will completely stop the loop, and with continue you will stop the execution of the commands in the loop and jump to the next value in the series.

One liners bash for loop

When using bash, the for loops are not always inserted in scripts, so you may find yourself using them directly in the command line. For this situations you need to use one liners.

Using one liners for loop with counters

When you are counting the times a command will be repeated (not very used in command line actually) you have one these syntax options.

for i in {n..m}; do [some command]; done

Where n is the lower number and m the higher one, so if you want to say Hello 3 times.

for i in {1..3}; do echo 'hello'; done

The other option is:

for ((i=n;i<=m;i++)); do [command]; done

Once again n is the lower number and m the higher, i++ is a counter, that is incrementing one by one. To do the same example as above.

for((i=1;i<=3;i++)); do echo "hello"; done

In the parenthesis you have three parts, the first one is setting the initial value i=1, the second is comparing a condition, i<=3, and the last one is the counter i++.

You can do some pretty interesting things with this.

for((i=0;i<=30;i+=2)); do echo "$i is even"; done

It will count the even numbers up to 30.

But the real reason to work with bash for loop in command line, and using one liners is to work with files.

Let's say you want to copy backup all pdf files.

for i in *.pdf; do cp $i /backup/; done

Add a extension .bak to all .txt files.

for i in *.txt; do mv $i `basename $i sh`.bak; done

Last updated on: June 18th, 2013

By: Guillermo Garron