Control Structures


The TC Shell uses many of the same control structures as the Bourne Again Shell. In each case the syntax is different, but the effects are the same. This section summarizes the differences between the control structures in the two shells. For more information refer to "Control Structures" on page 524.

if

The syntax of the if control structure is

if (expression) simple-command 


The if control structure works only with simple commands, not with pipes or lists of commands. You can use the if...then control structure (page 368) to execute more complex commands.

tcsh $ cat if_1 #!/bin/tcsh # Routine to show the use of a simple if control structure. # if ( $#argv == 0 ) echo "if_1: there are no arguments" 


The if_1 script checks whether it was called without any arguments. If the expression enclosed in parentheses evaluates to truethat is, if zero arguments were on the command linethe if structure displays a message.

In addition to logical expressions such as the one the if_1 script uses, you can use expressions that return a value based on the status of a file. The syntax for this type of expression is

n filename 


where n is from the list in Table 9-8.

Table 9-8. Value of n

n

Meaning

b

File is a block special file

c

File is a character special file

d

File is a directory file

e

File exists

f

File is an ordinary or directory file

g

File has the set-group-ID bit set

k

File has the sticky bit (page 955) set

l

File is a symbolic link

o

File is owned by user

p

File is a named pipe (FIFO)

r

The user has read access to the file

s

File is not empty (has nonzero size)

S

File is a socket special file

t

File descriptor (a single digit replacing filename) is open and connected to the screen

u

File has the set-user-ID bit set

w

User has write access to the file

x

User has execute access to the file

X

File is either a builtin or an executable found by searching the directories in $path

z

File is 0 bytes long


If the result of the test is true, the expression has a value of 1; if it is false, the expression has a value of 0. If the specified file does not exist or is not accessible, tcsh evaluates the expression as 0. The following example checks whether the file specified on the command line is an ordinary or directory file (and not a device or other special file):

tcsh $ cat if_2 #!/bin/tcsh if -f $1 echo "Ordinary or Directory file" 


You can combine operators where it makes sense. For example, ox filename is true if you own and have execute permission for the file. This expression is equivalent to o filename && x filename.

Some operators return useful information about a file other than reporting true or false. They use the same n filename format, where n is one of the values shown in Table 9-9.

Table 9-9. Value of n

n

Meaning

A

The last time the file was accessed.[*]

A:

The last time the file was accessed displayed in a human-readable format.

M

The last time the file was modified.[*]

M:

The last time the file was modified displayed in a human-readable format.

C

The last time the file's inode was modified.[*]

C:

The last time the file's inode was modified displayed in a human-readable format.

D

Device number for the file. This number uniquely identifies the device (disk partition, for example) on which the file resides.

I

Inode number for the file. The inode number uniquely identifies a file on a particular device.

F

A string of the form device:inode. This string uniquely identifies a file anywhere on the system.

N

Number of hard links to the file.

P

The file's permissions, shown in octal, without a leading 0.

U

Numeric user ID of the file's owner.

U:

Username of the file's owner.

G

Numeric group ID of the file's group.

G:

Name of the file's group.

Z

Number of bytes in the file.


[*] Time measured in seconds from the epoch (usually the start of January 1, 1970).

You can use only one of these operators in a given test, and it must appear as the last operator in a multiple-operator sequence. Because 0 can be a valid response from some of these operators (for instance, the number of bytes in a file might be 0), most return 1 on failure instead of the 0 that the logical operators return on failure. The one exception is F, which returns a colon if it cannot determine the device and inode for the file.

When you want to use one of these operators outside of a control structure expression, you can use the filetest builtin to evaluate a file test and report the result:

tcsh $ filetest -z if_1 0 tcsh $ filetest -F if_1 2051:12694 tcsh $ filetest -Z if_1 131 


goto

The goto statement has the following syntax:

goto label 


A goto builtin transfers control to the statement beginning with label:. The following script fragment demonstrates the use of goto:

tcsh $ cat goto_1 #!/bin/tcsh # # test for 2 arguments # if ($#argv == 2) goto goodargs echo "Usage: goto_1 arg1 arg2" exit 1 goodargs: ... 


The goto_1 script displays a usage message (page 528) when it is called with more or fewer than two arguments.

Interrupt Handling

The onintr statement transfers control when you interrupt a shell script. The format of an onintr statement is

onintr label 


When you press the interrupt key during execution of a shell script, the shell transfers control to the statement beginning with label:. This statement allows you to terminate a script gracefully when it is interrupted. You can use it to ensure that when you interrupt a shell script, the script removes temporary files before returning control to the parent shell.

The following script demonstrates onintr. It loops continuously until you press the interrupt key, at which time it displays a message and returns control to the shell:

tcsh $ cat onintr_1 #!/bin/tcsh # demonstration of onintr onintr close while ( 1 )     echo "Program is running."     sleep 2 end close: echo "End of program." 


If a script creates temporary files, you can use onintr to remove them.

close: rm -f /tmp/$$* 


The ambiguous file reference /tmp/$$* matches all files in /tmp that begin with the PID number of the current shell. Refer to page 562 for a description of this technique for naming temporary files.

if...then...else

The if...then...else control structure has three forms. The first form, an extension of the simple if structure, executes more complex commands or a series of commands if expression is true. This form is still a one-way branch.

if (expression) then   commands endif 


The second form is a two-way branch. If expression is true, the first set of commands is executed. If it is false, the set of commands following else is executed.

if (expression) then   commands else commands endif 


The third form is similar to the if...then...elif structure (page 531). It performs tests until it finds an expression that is true and then executes the corresponding commands.

if (expression) then      commands else if (expression) then    commands . . . else commands endif 


The following program assigns a value of 0, 1, 2, or 3 to the variable class based on the value of the first command line argument. The program declares the variable class at the beginning for clarity; you do not need to declare it before its first use. Also for clarity, the script assigns the value of the first command line argument to number.

tcsh $ cat if_else_1 #!/bin/tcsh # routine to categorize the first # command line argument set class set number = $argv[1] # if ($number < 0) then     @ class = 0 else if (0 <= $number && $number < 100) then     @ class = 1 else if (100 <= $number && $number < 200) then     @ class = 2 else     @ class = 3 endif # echo "The number $number is in class ${class}." 


The first if statement tests whether number is less than 0. If it is, the script assigns 0 to class and transfers control to the statement following endif. If it is not, the second if tests whether the number is between 0 and 100. The && is the Boolean AND operator, yielding a value of true if the expression on each side is true. If the number is between 0 and 100, 1 is assigned to class and control is transferred to the statement following endif. A similar test determines whether the number is between 100 and 200. If it is not, the final else assigns 3 to class. The endif closes the if control structure. The final statement uses braces ({}) to isolate the variable class from the following period. The braces isolate the period for clarity; the shell does not consider a punctuation mark to be part of a variable name. The braces would be required if you wanted other characters to follow immediately after the variable.

foreach

The foreach structure parallels the bash for...in structure (page 537). The syntax is

foreach loop-index (argument-list)     commands end 


This structure loops through commands. The first time through the loop, the structure assigns the value of the first argument in argument-list to loop-index. When control reaches the end statement, the shell assigns the value of the next argument from argument-list to loop-index and executes the commands again. The shell repeats this procedure until it exhausts argument-list.

The following tcsh script uses a foreach structure to loop through the files in the working directory containing a specified string of characters in their filename and to change the string. For example, you can use it to change the string memo in filenames to letter. The filenames memo.1, dailymemo, and memories would change to letter.1, dailyletter, and letterries.

This script requires two arguments: the string to be changed (the old string) and the new string. The argument-list of the foreach structure uses an ambiguous file reference to loop through all filenames that contain the first argument. For each filename that matches the ambiguous file reference, the mv utility changes the filename. The echo and sed commands appear within back ticks (`) that indicate command substitution: Executing the commands within the back ticks replaces the back ticks and everything between them. Refer to "Command Substitution" on page 327 for more information. The sed utility (page 641) substitutes the first argument for the second argument in the filename. The $1 and $2 are abbreviated forms of $argv[1] and $argv[2].

tcsh $ cat ren #!/bin/tcsh # Usage:        ren arg1 arg2 #               changes the string arg1 in the names of files #               in the working directory into the string arg2 if ($#argv != 2) goto usage foreach i ( *$1* )    mv $i `echo $i  sed -n s/$1/$2/p` end exit 0 usage: echo "Usage: ren arg1 arg2" exit 1 


Optional

The next script uses a foreach loop to assign the command line arguments to the elements of an array named buffer:

tcsh $ cat foreach_1 #!/bin/tcsh # routine to zero-fill argv to 20 arguments # set buffer = (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) set count = 1 # if ($#argv > 20) goto toomany # foreach argument ($argv[*])     set buffer[$count] = $argument     @ count++ end # REPLACE command ON THE NEXT LINE WITH # THE PROGRAM YOU WANT TO CALL. exec command $buffer[*] # toomany: echo "Too many arguments given." echo "Usage: foreach_1 [up to 20 arguments]" exit 1 


The foreach_1 script calls another program named command with a command line guaranteed to contain 20 arguments. If foreach_1 is called with fewer than 20 arguments, it fills the command line with zeros to complete the 20 arguments for command. Providing more than 20 arguments causes it to display a usage message and exit with an error status of 1.

The foreach structure loops through the commands one time for each command line argument. Each time through the loop, foreach assigns the value of the next argument from the command line to the variable argument. Then the script assigns each of these values to an element of the array buffer. The variable count maintains the index for the buffer array. A postfix operator increments the count variable using @ (@ count++). The exec builtin (bash and tcsh; page 574) calls command so that a new process is not initiated. (Once command is called, the process running this routine is no longer needed so a new process is not required.)


while

The syntax of the while structure is

while (expression)    commands end 


This structure continues to loop through commands while expression is true. If expression is false the first time it is evaluated, the structure never executes commands.

tcsh $ cat while_1 #!/bin/tcsh # Demonstration of a while control structure. # This routine sums the numbers between 1 and n, # with n being the first argument on the command # line. # set limit = $argv[1] set index = 1 set sum = 0 # while ($index <= $limit)     @ sum += $index     @ index++ end # echo "The sum is $sum" 


This program computes the sum of all integers up to and including n, where n is the first argument on the command line. The += operator assigns the value of sum + index to sum.

break and continue

You can interrupt a foreach or while structure with a break or continue statement. These statements execute the remaining commands on the line before they transfer control. The break statement transfers control to the statement after the end statement, terminating execution of the loop. The continue statement transfers control to the end statement, which continues execution of the loop.

switch

The switch structure is analogous to the bash case structure (page 545):

switch (test-string)   case pattern: commands breaksw case pattern: commands breaksw ... default:   commands breaksw endsw 


The breaksw statement transfers control to the statement following the endsw statement. If you omit a breaksw, control falls through to the next command. You can use any of the special characters listed in Table 13-2 on page 546 within pattern except the pipe symbol (|).

tcsh $ cat switch_1 #!/bin/tcsh # Demonstration of a switch control structure. # This routine tests the first command line argument # for yes or no in any combination of uppercase and # lowercase letters. # # test that argv[1] exists if ($#argv != 1) then     echo "Usage: switch_1 [yes|no]"     exit 1 else # argv[1] exists, set up switch based on its value    switch ($argv[1])    # case of YES          case [yY][eE][sS]:          echo "Argument one is yes."          breaksw     #     # case of NO          case [nN][o0]:          echo "Argument one is no."     breaksw     #     # default case          default:          echo "Argument one is neither yes nor no."          breaksw     endsw endif 





A Practical Guide to UNIX[r] for Mac OS[r] X Users
A Practical Guide to UNIX for Mac OS X Users
ISBN: 0131863339
EAN: 2147483647
Year: 2005
Pages: 234

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net