Loops in shell scripts

Slashdot it! Delicious Share on Facebook Tweet! Digg!
tiero, 123RF.com

tiero, 123RF.com

Running in Circles

Programming loops allow one-time or multiple execution of instructions. The condition for the loop can exist both outside and inside it.

With loops, you can execute part of a shell script over and over until an ending condition terminates it. You can use loops in menu controls and data processing. Without loops, you would need to start the scripts every time you wanted to process a piece of data.

Building Loops

A loop begins with for , while , or until (the loop header). After that follows a do statement that ends with done . Between do and done are the statements to execute (the loop body):

for / while / until [LOOP HEADER]
do
  [commands] [LOOP BODY]
done

In the loop body, apart from the commands, you can also add some controlling elements for the loop.

For example, using the break command, you terminate the loop execution and let the rest of the script be processed. You use continue to terminate the current cycle and proceed to the next one. With both of these commands, you can indicate the number of levels you want to jump in nested loops.

If the script were expecting another program to run, you would use wait . With exit , you terminate the loop immediately and completely (wait and exit aren't typical loop commands, but they do complement their functions in meaningful ways).

For Loop

A for loop requires a data feed. Each run-through is carried out for a single parameter that's extracted from a list, calculated from an increment or obtained from another data source. Basically, the for loop runs as long as the data is present. Of course, you can set a premature loop termination by using simple if or multiple case branching.

You can set parameters for the loop processing, in the following form:

for VARIABLE in PARAMETER1, PARAMETER2 ......
do
......
done

In practice, these parameters could be filenames, directories (backed up first!), users, applications, machine names, IP addresses, or anything else. Listing 1 shows a minimal example. Run it and see what it does. All code examples for this article are available online [1].

Listing 1

Setting Parameters

01 #! /bin/sh
02 for k in a  b  c
03 do
04    echo $k
05 done

Using the built-in math skills of Bash, you can create a counter, a feature missing in many other shells. Using counters, you can uniformly increment or decrement variables. Note that you should use #!/bin/bash as the first line of the shell script. Otherwise, you'll get error messages instead of counters. Take a look at Listing 2.

Listing 2

shellcounter.sh

01 #!/bin/bash
02 echo "increasing"
03
04 # "k=1" -> Variables initial value
05 # "k<5" -> Condition (k must be less than 5 to execute)
06 # "k++" -> Increment k by 1 in after each cycle
07 for ((k=1; k<5; k++))
08 do
09  echo $k
10 done
11
12 echo "decreasing"
13 for ((k=4; k>0; k--))
14 do
15  echo $k
16 done
17
18 echo "increasing with a larger increment"
19 for ((k=10; k<50; k=k+10))
20 do
21  echo $k
22 done
23
24 echo "increasing with a quadratic increment"
25 for ((k=2; k<50; k=k*k))
26 do
27  echo $k
28 done

The structure of the "calculated" for loop header begins with the definition of the variable's initial value. This is followed by a condition (minimum/maximum value of the variable) and the increment (or decrement) statement for the value. Figure 1 shows the loop's execution.

Figure 1: Execution of the shellcounter.sh script.

In the first two loops, the increment/decrement value is 1. The third loop shows the calculation method for a different fixed increment value. In the last loop, you get a quadratic increment by multiplying the variable by itself.

In this case, the initial variable value cannot be 0 or 1 , or you'll get an infinite loop. The parameters for the for loop can also come from other applications. The call takes the following form:

for VARIABLE in $([CALL APPLICATION])

Or the following:

for VARIABLE in `[CALL APPLICATION]`

You can use just about anything as the data source that produces unique values separated by spaces.

In Listing 3, you first determine the types for all objects found by ls -1 in the current subdirectory using file . The fold is simply for output formatting: It folds text at 50 characters.

Listing 3

datasource.sh

01 #!/bin/sh
02
03 echo "Determining the data type for a for-loop"
04 for k in $(ls -1)
05 do
06   echo "--------------------------------------------"
07   file $k | fold -sbw 50
08 done
09 echo "--------------------------------------------"
10
11 echo "  "
12 echo "Using a text file to derive values"
13 echo " "
14 for k in `cat input.txt`
15 do
16   echo $k
17 done
18 echo " "
19
20 echo "Database query (sqlite) as data source"
21 echo " "
22 for k in $(sqlite3 test.db 'select one from tbl1 where two<500;')
23 do
24   echo $k
25 done

You then read a text file that returns a name per line. Each loop cycle sets the k variable to one of these names. Finally, you read a filed called one from a database table for all the values in the two field less than 500. The database table has just four entries and registers 1, 2, and 4 meet the condition. Figure 2 shows the results.

Figure 2: Result of the datasource.sh shell script shown in Listing 3.

Buy this article as PDF

Express-Checkout as PDF

Pages: 5

Price $0.99
(incl. VAT)

Buy Ubuntu User

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content