| 
 | 
< Day Day Up > | 
 | 
8.6. Looping CommandsLooping commands are used to execute a command or group of commands a set number of times or until a certain condition is met. The Bourne shell has three types of loops: for, while, and until. 8.6.1 The for CommandThe for looping command is used to execute commands a finite number of times on a list of items. For example, you might use this loop to execute the same commands on a list of files or usernames. The for command is followed by a user-defined variable, the keyword in, and a list of words. The first time in the loop, the first word from the wordlist is assigned to the variable, and then shifted off the list. Once the word is assigned to the variable, the body of the loop is entered, and commands between the do and done keywords are executed. The next time around the loop, the second word is assigned to the variable, and so on. The body of the loop starts at the do keyword and ends at the done keyword. When all of the words in the list have been shifted off, the loop ends and program control continues after the done keyword. FORMAT for variable in word_list do command(s) done Example 8.25.(The Script) #!/bin/sh # Scriptname: forloop 1 for pal in Tom Dick Harry Joe 2 do 3 echo "Hi $pal" 4 done 5 echo "Out of loop" (The Output) $ forloop Hi Tom Hi Dick Hi Harry Hi Joe Out of loop EXPLANATION 
 Example 8.26.(The Command Line) 1 $ cat mylist tom patty ann jake (The Script) #!/bin/sh # Scriptname: mailer 2 for person in `cat mylist` do 3 mail $person < letter echo $person was sent a letter. 4 done 5 echo "The letter has been sent." EXPLANATION 
 Example 8.27.
(The Script)
    #!/bin/sh
    # Scriptname: backup
    # Purpose:
    # Create backup files and store them in a backup directory
1   dir=/home/jody/ellie/backupscripts
2   for file in memo[1-5]
    do
3       if [ -f $file ]
        then
             cp $file $dir/$file.bak
             echo "$file is backed up in $dir"
        fi
    done
(The Output)
memo1 is backed up in /home/jody/ellie/backupscripts
memo2 is backed up in /home/jody/ellie/backupscripts
memo3 is backed up in /home/jody/ellie/backupscripts
memo4 is backed up in /home/jody/ellie/backupscripts
memo5 is backed up in /home/jody/ellie/backupscripts
EXPLANATION 
 8.6.2 The $* and $@ Variables in WordlistsWhen expanded, the $* and $@ are the same unless enclosed in double quotes. $* evaluates to one string, whereas $@ evaluates to a list of separate words. Example 8.28.
(The Script)
    #!/bin/sh
    # Scriptname: greet
1   for name in $*        # Same as for name in $@
2   do
        echo Hi $name
3   done
(The Command Line)
$ greet Dee Bert Lizzy Tommy
Hi Dee
Hi Bert
Hi Lizzy
Hi Tommy
EXPLANATION 
 Example 8.29.
(The Script)
    #!/bin/sh
    # Scriptname:permx
1   for file         # Empty wordlist
    do
2       if [ -f $file -a ! -x $file ]
        then
3           chmod +x $file
            echo $file now has execute permission
        fi
    done
(The Command Line)
4   $ permx *
    addon now has execute permission
    checkon now has execute permission
    doit now has execute permission
EXPLANATION 
 8.6.3 The while CommandThe while command evaluates the command immediately following it and, if its exit status is 0, the commands in the body of the loop (commands between do and done) are executed. When the done keyword is reached, control is returned to the top of the loop and the while command checks the exit status of the command again. Until the exit status of the command being evaluated by the while becomes nonzero, the loop continues. When the exit status reaches nonzero, program execution starts after the done keyword. FORMAT 
while command
do
    command(s)
done
Example 8.30.
(The Script)
     #!/bin/sh
     # Scriptname: num
1    num=0                         # Initialize num
2    while  [ $num -lt 10 ]        # Test num with test command
    do
          echo  -n $num
3         num=`expr  $num + 1`     # Increment num
    done
    echo "\nAfter loop exits, continue running here"
(The Output)
0123456789
After loop exits, continue running here
EXPLANATION 
 Example 8.31.
(The Script)
     #!/bin/sh
     # Scriptname: quiz
1    echo "Who was the chief defense lawyer in the OJ case?"
     read answer
2    while [ "$answer" != "Johnny" ]
3    do
4        echo  "Wrong try again!"
         read answer
5    done
6    echo You got it!
(The Output)
$ quiz
Who was the chief defense lawyer in the OJ case? Marcia
Wrong try again!
Who was the chief defense lawyer in the OJ case?  I give up
Wrong try again!
Who was the chief defense lawyer in the OJ case?  Johnny
You got it!
EXPLANATION 
 Example 8.32.
(The Script)
    #!/bin/sh
    # Scriptname: sayit
    echo Type q to quit.
    go=start
1   while [ -n "$go" ]      # Make sure to double quote the variable
    do
2        echo -n I love you.
3        read word
4        if [ "$word" = q -o "$word" = Q ]
         then
             echo "I'll always love you!"
             go=
         fi
    done
(The Output)
$ sayit
Type q to quit.
I love you.     <- When user presses the Enter key, the program continues
I love you.
I love you.
I love you.
I love you.q
I'll always love you!
$
EXPLANATION 
 8.6.4 The until CommandThe until command is used like the while command, but executes the loop statements only if the command after until fails; that is, if the command returns an exit status of nonzero. When the done keyword is reached, control is returned to the top of the loop and the until command checks the exit status of the command again. Until the exit status of the command being evaluated by until becomes 0, the loop continues. When the exit status reaches 0, the loop exits, and program execution starts after the done keyword. FORMAT 
until command
do
    command(s)
done
Example 8.33.
(The Script)
     #!/bin/sh
1    until who | grep linda
2    do
         sleep 5
3    done
     talk linda@dragonwings
EXPLANATION 
 Example 8.34.
(The Script)
     #!/bin/sh
     # Scriptname: hour
1    hour=1
2    until [ $hour  -gt 24 ]
     do
3      case "$hour" in
       [0-9] |1[0-1])   echo  "Good morning!"
             ;;
       12)  echo  "Lunch time."
             ;;
       1[3-7])   echo  "Siesta time."
             ;;
       *)   echo  "Good night."
             ;;
       esac
4      hour=`expr $hour + 1`
5   done
(The Output)
$ hour
Good morning!
Good morning!
    ...
Lunch time
Siesta time
    ...
Good night.
    ...
EXPLANATION 
 8.6.5 Looping Control CommandsIf some condition occurs, you may want to break out of a loop, return to the top of the loop, or provide a way to stop an infinite loop. The Bourne shell provides loop control commands to handle these kinds of situations. The shift CommandThe shift command shifts the parameter list to the left a specified number of times. The shift command without an argument shifts the parameter list once to the left. Once the list is shifted, the parameter is removed permanently. Often, the shift command is used in a while loop when iterating through a list of positional parameters. FORMAT shift [n] Example 8.35.
(Without a loop)
(The Script)
     #!/bin/sh
1    set joe mary tom sam
2    shift
3    echo $*
4    set `date`
5    echo  $*
6    shift 5
7    echo  $*
8    shift 2
(The Output)
3    mary tom sam
5    Fri Sep 9 10:00:12 PDT 2004
7    2004
8    cannot shift
EXPLANATION 
 Example 8.36.
(With a loop)
(The Script)
     #!/bin/sh
     # Name: doit
     # Purpose: shift through command-line arguments
     # Usage: doit [args]
1     while [  $# -gt  0 ]
      do
2        echo  $*
3        shift
4    done
(The Command Line)
$ doit a b c d e
a b c d e
b c d e
c d e
d e
e
EXPLANATION 
 Example 8.37.
(The Script)
     #!/bin/sh
     # Scriptname: dater
     # Purpose: set positional parameters with the set command
     # and shift through the parameters.
1   set `date`
2   while [ $# -gt 0 ]
    do
3       echo $1
4       shift
    done
(The Output)
$ dater
Sat
Oct
16
12:12:13
PDT
2004
EXPLANATION 
 The break CommandThe built-in break command is used to force immediate exit from a loop, but not from a program. (To leave a program, the exit command is used.) After the break command is executed, control starts after the done keyword. The break command causes an exit from the innermost loop, so if you have nested loops, the break command takes a number as an argument, allowing you to break out of a specific outer loop. If you are nested in three loops, the outermost loop is loop number 3, the next nested loop is loop number 2, and the innermost nested loop is loop number 1. The break is useful for exiting from an infinite loop. FORMAT break [n] Example 8.38.
    #!/bin/sh
1   while true; do
2       echo Are you ready to move on\?
        read answer
3       if [  "$answer"  =  Y -o "$answer" = y  ]
        then
EXPLANATION 
 The continue CommandThe continue command returns control to the top of the loop if some condition becomes true. All commands below the continue will be ignored. If nested within a number of loops, the continue command returns control to the innermost loop. If a number is given as its argument, control can then be started at the top of any loop. If you are nested in three loops, the outermost loop is loop number 3, the next nested loop is loop number 2, and the innermost nested loop is loop number 1.[3] 
 FORMAT continue [n] Example 8.39.(The mailing List) $ cat mail_list ernie john richard melanie greg robin (The Script) #!/bin/sh # Scriptname: mailem # Purpose: To send a list EXPLANATION 
 8.6.6 Nested Loops and Loop ControlWhen using nested loops, the break and continue commands can be given a numeric, integer argument so that control can go from the inner loop to an outer loop. Example 8.40.
(The Script)
     #!/bin/sh
     # Scriptname: months
EXPLANATION 
 8.6.7 I/O Redirection and SubshellsInput can be piped or redirected to a loop from a file. Output can also be piped or redirected to a file from a loop. The shell starts a subshell to handle I/O redirection and pipes. Any variables defined within the loop will not be known to the rest of the script when the loop terminates. Redirecting the Output of a Loop to a FileSee Example 8.41 for a demonstration of how to redirect the output of a loop to a file. Example 8.41.(The Command Line) 1 $ cat memo abc def ghi (The Script) #!/bin/sh # Program name: numberit # Put line numbers on all lines of memo 2 if [ $# -lt 1 ] then 3 echo "Usage: $0 filename " >&2 exit 1 fi 4 count=1 # Initialize count 5 cat $1 | while read line # Input is coming from file on command line do 6 [ $count -eq 1 ] && echo "Processing file $1..." > /dev/tty 7 echo $count $line 8 count=`expr $count + 1` 9 done > tmp$$ # Output is going to a temporary file 10 mv tmp$$ $1 (The Command Line) 11 $ numberit memo Processing file memo... 12 $ cat memo 1 abc 2 def 3 ghi EXPLANATION 
 Example 8.42.(The Input File) $ cat testing apples pears peaches (The Script) #!/bin/sh # This program demonstrates the scope of variables when # assigned within loops where the looping command uses # redirection. A subshell is started when the loop uses # redirection, making all variables created within the loop # local to the shell where the loop is being executed. 1 while read line do 2 echo $line # This line will be redirected to outfile 3 name=JOE 4 done < testing > outfile # Redirection of input and output 5 echo Hi there $name (The Output) 5 Hi there EXPLANATION 
 Piping the Output of a Loop to a UNIX CommandOutput can be either piped to another command(s) or redirected to a file. Example 8.43.
(The Script)
     #!/bin/sh
1    for i in 7 9 2 3 4  5
2    do
         echo  $i
3    done | sort –n
(The Output)
2
3
4
5
7
9
EXPLANATION 
 8.6.8 Running Loops in the BackgroundLoops can be executed to run in the background. The program can continue without waiting for the loop to finish processing. Example 8.44.
(The Script)
     #!/bin/sh
1    for person in bob jim joe sam
     do
2        mail $person < memo
3    done &
EXPLANATION 
 8.6.9 The exec Command and LoopsThe exec command can be used to open or close standard input or output without creating a subshell. Therefore, when starting a loop, any variables created within the body of the loop will remain when the loop completes. When using redirection in loops, any variables created within the loop are lost. The exec command is often used to open files for reading and writing, either by name or by file descriptor number. Recall that file descriptors 0, 1, and 2 are reserved for standard input, output, and error. If a file is opened, it will receive the next available file descriptor. For example, if file descriptor 3 is the next free descriptor, the new file will be assigned file descriptor 3. Example 8.45.(The File) 1 $ cat tmp apples pears bananas pleaches plums (The Script) #!/bin/sh # Scriptname: speller # Purpose: Check and fix spelling errors in a file 2 exec < tmp # Opens the tmp file 3 while read line # Read from the tmp file do 4 echo $line 5 echo –n "Is this word correct? [Y/N] " 6 read answer < /dev/tty # Read from the terminal 7 case "$answer" in 8 [Yy]*) 9 continue;; *) echo "What is the correct spelling? " 10 read word < /dev/tty 11 sed "s/$line/$word/g" tmp > error 12 mv error tmp 13 echo $line has been changed to $word. esac 14 done EXPLANATION 
 8.6.10 IFS and LoopsThe shell's internal field separator (IFS) evaluates to spaces, tabs, and the newline character. It is used as a word (token) separator for commands that parse lists of words, such as read, set, and for. It can be reset by the user if a different separator will be used in a list. Before changing its value, it is a good idea to save the original value of the IFS in another variable. Then it is easy to return to its default value, if needed. Example 8.46.
(The Script )
     #/bin/sh
     # Scriptname: runit
     # IFS is the internal field separator and defaults to
     # spaces, tabs, and newlines.
     # In this script it is changed to a colon.
1    names=Tom:Dick:Harry:John
2    OLDIFS="$IFS"     # Save the original value of IFS
3    IFS=":"
4    for persons in $names
     do
5        echo  Hi $persons
     done
6    IFS="$OLDIFS"             # Reset the IFS to old value
7    set Jill Jane Jolene      # Set positional parameters
8    for girl in $*
     do
9        echo Howdy $girl
     done
(The Output)
5    Hi Tom
     Hi Dick
     Hi Harry
     Hi John
9    Howdy Jill
     Howdy Jane
     Howdy Jolene
EXPLANATION 
  | 
| 
 | 
< Day Day Up > | 
 |