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