More on C shell programming: You can try running each of the example C shell scripts shown below. On acad1 they can be copied from the /u1/cfiles/cshell directory, as in this example which copies all of the example C shell programs to a directory called shell within your home directory: cd mkdir shell cd shell cp /u1/cfiles/cshell/* . (Note the period in the last command. It is needed to tell UNIX to copy to your current directory.) On Linux, try copying a desired script from the Web page and pasting into an empty file in your editor on Linux. See if you can understand how the following C shell programs work. A) Loops: 1) While loop: The syntax is as follows: while (boolean_expression) command(s)... end Here is a simple example. Note that you MUST put a space after the @ sign in the line that does the arithmetic. #! /bin/csh -f # # Filename: while1 # set num=0 while ($num < 10) @ num++ # This is how to increment a variable echo "The value of num is: $num" end You can use break to get out of an infinite loop as in: #! /bin/csh -f # # Filename: while2 # set num=0 while (1) @ num++ echo "The value of num is: $num" if ($num > 10) break end echo "while loop has ended" Compare the last shell program to this one: #! /bin/csh -f # # Filename: while3 # set num=0 while (1) @ num++ echo "The value of num is: $num" if ($num > 10) exit(1) end echo "while loop has ended" 2) Repeat loop: The syntax is simple: repeat n command For example: #! /bin/csh -f # # Filename: repeat1 # echo "Start of script" repeat 5 echo "" echo "End of script" This example just prints 5 blank lines on the screen. 3) Foreach loop This type of loop is intended for processing a list of items. The syntax is: foreach item (list_of_items) command(s)... end Here is an easy example. It uses the head command to show the first 6 lines of a few files: #! /bin/csh -f # # Filename: foreach1 # foreach value (while1 while2 repeat1) head -6 $value end Here is another example. It gives a long listing of each file that starts with while. Note the use of the * wildcard. #! /bin/csh -f # # Filename: foreach2 # foreach file (while*) ls -l $file end Note that file is simply a shell variable. You could use another name instead of file. Call it item if you like. Here is a more advanced shell script that uses a foreach loop. It uses a few commands that may be new to you, but they will be explained along the way. This script could best be tried out by copying it to your home directory and running it there. For example, use: cd cp shell/foreach3 . foreach3 #! /bin/csh -f # # Filename: foreach3 # # Reference: UNIX C Shell Desk Reference by Martin R. Arick # # This program gives a long listing of all the files in the directories # under the current directory. It does not process directories within # directories. # foreach entry (*) if (-d $entry) then # this is a directory pushd $entry >& /dev/null # change to this directory echo "------------------------------------------------------" echo "--- Contents of $cwd directory follows ---" ls -l popd >& /dev/null # return to the original directory endif end echo "--- End of listing ---" Note that pushd changes to a new directory and pushes the old working directory onto the directory stack (so that you can easily get it back later). The >& is used to redirect the output and any error messages to /dev/null, which is the UNIX trash bin for unwanted bits. Anything written to /dev/null really goes nowhere (is thrown away). The popd command pops the last directory off of the directory stack and changes to it as the current directory. Its output is also redirected since we don't want this output to appear on the screen and mess up what our program is printing. (The normal output of pushd and popd is to show what is currently on the directory stack.) Finally, note that cwd is a shell variable that holds the current working directory. B) Making a choice: 1) If statements: There are several forms of if statement. The syntax for several are shown below: if (expression) command if (expression) then command(s)... endif if (expression) then command(s)... else command(s)... endif if (expression) then command(s)... else if (expression) then command(s)... else command(s)... endif The following example is a C shell copy command that can copy a file or files to your current directory without the need for typing a . like cp requires. #! /bin/csh -f # # Filename: copy # # The syntax is: copy file(s) (to copy to current directory) # or # copy file(s) destination # if ($#argv == 0 || $#argv > 2) then echo "ERROR -- correct syntax:" echo "copy file(s)" echo " or" echo "copy file(s) destination" exit(1) # a nonzero exit status indicates an error else if ($#argv == 1) then cp $argv[1] . else # $#argv must be 2 cp $argv[1] $argv[2] endif exit(0) Note the use of exit. This would allow another program to test exit status to determine whether copy succeeded or failed. 2) Switch statement: The syntax is as follows: switch (variable) case string1: command(s)... breaksw case string2: command(s)... breaksw default: command(s)... endsw Here is an easy example: #! /bin/csh -f # # Filename: switch1 # # Syntax: switch1 string # # The idea is to use one, two, or three for the string. # if ($#argv != 1) then echo "ERROR -- one command line argument is required" exit(1) endif switch ($argv[1]) case one: echo "This is case one" breaksw case two: echo "This is case two" breaksw case three: echo "This is case three" breaksw default: echo "You did not enter one, two, or three" endsw echo "End of program" exit(0) 3) Conditions: Boolean conditions are used in loops and ifs. You can compare values to get a boolean condition. Valid comparison operators are: == equals != not equals Some comparisons are only valid for numbers. These include: < > <= >= Examples: if ($num > 6) ... if ($string == "first") ... You can also test if a variable is defined by using a ? as shown in this example: if ($?item) ... For strings that supposedly contain filenames, a number of tests are possible, such as the following: if ( -f $file) echo "$file is an actual file" if (! -f $file) echo "$file is not a file" if ( -d $file) echo "$file is a directory" if ( -x $file) echo "$file is executable" if ( -e $file) echo "The file $file does exist" if ( -r $file) echo "You have read access to file $file" if ( -w $file) echo "You have write access to file $file" if ( -o $file) echo "Your are the owner of file $file" Note that !, meaning not, can be inserted at the front of a condition. Finally, conditions can be combined by using || for or, && for and. See the copy script above for an example. To try on your own: Rewrite the copy script so that it copies just a single file at a time, and it includes a test to see if the source file exists before trying to copy it. Also include a test to see if any destination is a directory. If it is not a directory, see if the destination is a file. If the file already exists, refuse to do the copy and exit with a message saying that the file was not overwritten. If the destination is not a directory and there is no file already by that name, then do the copy. Intended usage: copy sample sample.bak (If sample.bak already exists, should refuse to overwrite.) copy /users/cfiles/cshell/while1 (will copy to current directory) copy $home/.cshrc $home/cshell (put a copy in your cshell directory) (Any of these commands should fail if the source file doesn't exist.) Another script that you can try on acad1 is /usr/local/bin/print. This is the print program that many people use to print a file on the acad1 system. Note that print is a C shell script. See if you can understand the IF tests that it includes.