CSI110
Lecture 7
Writing C Shell Scripts (1)
 Apart from functioning as an interactive command interpreter, the shell also defines a simple programming language
 A program written in this language is known as a shell procedure or shell script
 When a file containing a script is executed, the shell performs all the tasks in the file as though they had been entered individually
 In their most basic form, they are useful for performing frequently used combinations of actions
 As the shell language also includes variables, control structures and input and output features, more complex programs are possible
Invoking Shell Scripts
 There are two ways in which a shell script can be executed
by direct interpretation
by indirect interpretation
 Invoking a shell script by direct interpretation
%babe> csh file [arg...]
which runs the file using the C Shell
 Invoking a shell script by indirect interpretation
Make the file readable and executable
Execute it
%babe> file [arg...]
 In either case, the shell script will run in a separate sub-shell
 Type
pwd to display the name of the current directory Type the following into a file called try
cd /usr/lib
pwd
 Execute it using
csh try Now type
pwd again at the command line prompt Change
try's permissions so you can execute it by typingtry
at the command line prompt
 Type
pwd again at the command line prompt Why did we get this behaviour?
 We will discuss the relationship between the invoking shell and the invoked shell later
A Simple Example
 We're going to write a simple script to consult a database of users
 Copy the file
users from /tmp into your current directory A script called
find_user will contain a single line containing a search for a case insensitive occurrence of the first parameter given to find_user in users Positional parameters from the command line can be referred to from inside a script using the
$n symbol, where n is the parameter position If
find_user is called with the parameter staff (find_user staff), then $0 is find_user and $1 is staff. $2 ... $m are set to null Write the script, set execution rights on it, and run it
 Usually, user scripts are stored in the directory
~/bin, which is also added to your command search path Create a new directory
bin in your home directory and move find_user into it Edit your C Shell configuration file (
.cshrc in your home directory), to add ~/bin to the path Does it matter where in the path
~/bin is added? Enter a new C Shell
 You will now be able to run
find_user from anywhere If you add a new script to
~/bin during a C Shell, you will only be able to access it from anywhere in the current shell session if you run rehash If you run
find_user staff again it will fail, because find_user and users are no longer in the same directory Move
users to your home directory and modify the find_user script accordingly Do you need to run
rehash again?Shell Script Basics
 Filename extensions are not significant in UNIX
 So how does UNIX know how to execute a shell script?
 Executable files can be one of a number of types
 If the file starts with a magic number, then UNIX knows that it is a binary executable file
 Otherwise, if the first character in the file is not a
#, UNIX treats it as a Bourne Shell (sh) script If it starts with a
# and the second character is not !, then it is treated as a C Shell script If it starts with
#!, then UNIX invokes the program following the #! as the program to use to interpret the rest of the file E.g., edit
find_user, inserting #!/bin/csh as the first line, and re-run the program Now change the first line to read
#!/bin/cat and re-run the program again Although executable files starting with
# (and not #!) will invoke a C Shell, it is usually more efficient to use #!/bin/csh -f instead The
-f option to csh prevents the .cshrc file from being loaded, which results in faster loading/execution times In the remainder of these lectures, a commandlist is a sequence of zero or commands seaparated by NEWLINE or semi-colon characters, and a wordlist is a list of zero or more blank separated words
Csh Positional Parameters
 Apart from using
$0, $1, ..., $m to refer to positional parameters, you can also $argv[n] In addition,
$#argv is the number of positional parameters, and $argv[*] is a wordlist of all parameters (excluding the command name!) Be aware that although
$0 is the name of the command, $argv[0] is undefined! The equivalent of
$argv[*] is $* Re-write
find_user using the $argv[] notation instead of the $ notation In addition, use
echo to print the number of arguments that find_user was called with Call
find_user with no parameters Fix
find_user so it prints an appropriate error message instead
The foreach command
foreachcontrol_variable (wordlist)
commandlist
end
 Modify
find_user to accept an arbitrary number of positional parameters and to search users for each parameter If an
* appears as the wordlist, then UNIX assumes it is a reference to a filename and performs filename expansion on it Write
myls which lists the files in the current directory (use foreach and echo - do NOT simply call ls from within myls!) Modify
myls to take an optional command line argument and list only the files starting with the argument
The if command
(1)
if (expr) simple_command(2)
if (expr) thencommandlist1
[else
commandlist2]
endif
(3)
if (expr1) thencommandlist1
else if (expr2) then
commandlist2]
[else
commandlist3]
endif
 First form
if ($#argv == 1) grep -i $argv[1] ~/users
 Second form
if ($#argv == 1) then
grep -i $argv[1] ~/users
else
echo usage: $0 name-to-find
exit(1)
endif
 Third form
if ($#argv < 1 || $#argv >2) then
echo usage: $0 '[from-file] to-file'
exit(1)
else if ($#argv == 2) then
@from = $argv[1]
@to = $argv[2]
else
@to = $argv[1]
endif
 There can be any number of
else if constructs The
@ symbol is used to enable numerical computation. The reserved word set can be used instead, e.g., set from = $argv[1]
exit(n) is used to force terminate execution of a script, returning control to the invoking script or shell If
n is 0, then termination was normal If
n != 0, then termination is abnormal, and the value of n indicates which error occurred
n is the exit status of the script
The switch command
 Multiway branching
switch (str)
case pattern1:
commandlist1
breaksw
case pattern2:
commandlist2
breaksw
...
default:
commandlist
endsw
The while command
while (expr)
commandlist
end
 while ($#argv > 0)
grep -i $argv[1] ~/users
shift
end