Previous Table of Contents Next

The output of the ls command is passed to the for loop. The for loop assigns the first value in the list from the ls to the variable named FILE. Then the appropriate statements are executed within the do and done statements until all output from the ls command is processed. You are prompted for a response by the first echo statement. If you answer with a q or Q, the for loop is exited via the break command. If you answer with a y or Y, the file is moved and the next file is processed. If you answer with any other response, the file is not moved and the next file is processed. Once all files have been processed the for loop automatically exits.


The while loop provides more control over command processing. It can be used to perform simple number control loops, process commands if another command is true, or process lines of information passed to it via a pipe. As long as the first command list returns a return exit code the while loop will continue to execute.


The format of the while loop follows.

     while command_list_1

C Shell
while (expr)

The while loop is used for multiple types of flow control. It is a highly flexible construct since it terminates based on the exit status of the last simple command in the first command list. This allows you to execute other commands based on the completion of commands repeatedly.

For example, the following while loop is very simple. It displays the numbers between 1 and 100. It is written as though it were a shell script. We assumed the name of cnt.

     cj> cat cnt
     while (( CNT <= HI ))
         echo $CNT
         (( CNT = CNT + 1 ))

The first line sets the variable CNT to the first parameter. If the first parameter is not provided then CNT is set to 1. The second line sets HI to the second parameter. If the second parameter is not given then HI is set to 100. So by default this loop counts from 1 to 100.

The (( CNT <= HI )) is the Korn shell's arithmetic command (a form of the let command). It checks for the condition of CNT being less than or equal to HI. The condition is true until CNT = 101. The echo statement displays the value of CNT. The next arithmetic statement increments the value of CNT by 1. The result of this loop is a list of numbers on your screen from one to a hundred.

For comparison in speed, you can replace the (( CNT <= HI )) statement with expr $CNT \<= $HI > /dev/null. Replace (( CNT = CNT + 1 )) with CNT=`expr $CNT + 1'.

Another example of the while loop shows how you can process a stream of data from a pipe command.

     cat /etc/passwd | \
         echo "$USERNAME\t$USRID\t$GRPID\t$HOMEDIR"

This script produces a simple listing of all login entries in the /etc/passwd file. The first line saves the IFS (internal field separator) to the variable OIFS. The second line sets IFS to a colon. The colon is used in the /etc/passwd file to separate fields of information. The third line displays a header for the output. The cat command pipes the contents of the /etc/passwd file into the while loop. The read statement reads one line of input at a time. Each field of the passwd file is set to its respective variable name on the read line. Then the echo statement displays the values of the current line that has been read.


The until loop reverses the termination condition used in the while loop. Instead of exiting when a return status of nonzero is returned from command_list_1, the until loop exits when a return status of zero is returned.


The format of the until statement follows.

     until command_list_1

C Shell
goto label

The until loop provides a way to loop while a condition is false or until the condition is true. This is useful when you need to ensure that some other process you have no control over has finished.

     until [ -f $FILE ]
         sleep 600

In this script we set FILE to be the first parameter from the command line or to the name "proc1.out." The until loop checks for the specified FILE. If the file does not exist, the internal part of the loop is executed. Thus if the file does not exist, the shell script sleeps for 600 seconds (10 minutes). After ten minutes a check is made to see if the file exists. If the file does exist the loop terminates.

You should not use the until loop in situations were you are waiting on a child process in the background to finish. In this situation use the wait command.


The internal break command is used to break out of a for, until, or while loop. You can use the break command to exit from within a loop but remain in the shell script.


Following is the format of the break statement.

     break [ n ]

C Shell
break [break . . .]


The following describes the argument that may be passed to the break command.

n Break n levels of loops. If you are nested inside more than one loop, you can use the break command to exit out to a higher level.

When the shell executes the break command, control immediately exits the loop. The shell continues execution as normal on the line after the loop's done delimiter.

The break command is normally used to exit infinite loops. Usually, some condition occurs, such as an error, or all processing has completed, which causes the break to exit the loop.

For example, the following code illustrates an infinite loop using a break statement to exit.

If you type break and press Return, the break statement breaks out of the loop.


The internal continue command is used in shell scripts to skip the remaining lines in a for, while, or until loop. The commands that would normally be executed in the proper sequence are skipped and the next iteration of the loop is executed from the top.


Following is the general format of the continue command.

     continue [ n ]

C Shell


The following argument may be passed to the continue command.

n The next iteration of the nth loop enclosing this loop. For example, if you specified continue 2, then execution would return to the next iteration of the loop that encloses the loop you are currently in.

When the shell executes the continue command, control immediately skips to the next iteration of the loop. If n is specified, then control is passed to the next iteration of the nth loop surrounding the current loop.

Usually, some condition occurs, such as an error or the process is not possible, that causes the continue to skip to the next step in the loop. For example, the following code illustrates a loop using a continue statement to skip processing if a file is not readable.

The for loop processes all positional parameters. The if statement checks for read permission on the current file. If the file is not readable, the next file is processed. The continue statement forces the next iteration of the for loop. If the file is readable, the remaining commands in the for loop are executed.


Shell functions provide the ability to write structured high level programs. Using functions can reduce redundant code and provide a more understandable and elegant shell script. Before functions were supported by the shell you had to pass parameters to subshell scripts. This worked but there were limitations and it was much slower.

You want to implement functions for code used repeatedly. For example, you might want to perform screen control. So you should create a cls and cursor function at the beginning of your program. If you use a set of functions in more than one shell script, you might consider placing the functions in a file by themselves. Then, at the beginning of each script that needs to use the functions, perform the . (dot) command on the file.


Following is the format of a function.

     function name { command_list ;}

The command list can be multiple lines of shell commands, including calls to other functions. If the } is on a line by itself you do not use the ;.

By using functions you can write complex shell scripts that perform well. You reduce the need to call subshells and keep most of the redundant activities in the current shell.

A few examples of functions you might find helpful in your scripts follow.

     function cls { # clears your terminal screen
              CLS=${CLS:-`tput clear`}
              print - "${CLS}\c" ;}

     function cursor { # positions the cursor on your terminal screen
       case "$TERM" in
         ansi|vt*) echo "\033[${1};${2}H\c" ;;
        adm*|tvi*) typeset -8 ROW=COL=0
           (( rrow = $1 + 8#037 ))
           (( ccol = $1 + 8#037 ))
           eval print - "\\033=\\${r}\\${c}\\c" ;} ;;
          wyse*) function cursor { echo "\033a${1}R${2}C\c" ;} ;;
       esac ;}

     # set your shell prompt to present working directory
     alias cd=_cd
     function _cd { cd ; PS1="cj:${PWD}-> " ;}

The internal return command is used to exit from a shell function without exiting the current shell. The concept is the same as the return function used in the C programming language. The return causes execution control to return to the level that called the function. A return code is always returned to the calling level.


Following is the general format of the return command.

     return [ n ]


The following argument may be passed to the return command.

n Used to set the return code of the function to n.
If n is not specified the return code of the last command is returned.

The return command causes termination of a function without terminating the current shell. It is useful in situations where you want to exit from a function based on a certain condition.

The return command can return specific return codes. You may find it beneficial to use the return codes in conditional statements. For instance, you may want to decide how to control a loop or if statement based on the return code of a function. The following code shows an example of a function with the possibility of returning different return codes:

Previous Table of Contents Next