Part of
the 22C:112, Operating Systems Notes
by
Douglas W. Jones
THE UNIVERSITY
OF IOWA
Department of Computer Science
Our lab systems run the tcsh shell, one of many Unix shells. The original, known as the Bourne shell (after its developer) was just sh. After the Bourne shell had developed into a rather ugly programming language, the C-shell csh was developed, trying to rationalize things while maintaining a degree of compatability. Other shells have emerged in the years since, such as the Bourne Again shell, bash. All of them have significant user communities.
Because all of the shells are incompatible with each other, every shell script should begin by designating its interpreter. This is done with an initial line that names the file to be executed:
#!/bin/tcsh
The loader, on seeing this line at the head of an executable file, goes and loads the named interpreter instead of loading the remainder of the file, and it then passes the entire file to the interpreter as input. This mechanism was designed for shells, but it can be used for any interpreted language.
This mechanism is a kluge. File attributes really ought to be encoded as some kind of file type, and file types probably should not be embedded in the data.
Having created a file, perhaps named shellscript, that begins as required, we need to make that file executable. We do this with the command:
chmod +x shellscript
The chmod command changes the access rights for the named file. The string +x means add the execute x right. The string -x would have removed execute rights.
To check the access rights on a file, do this:
ls -l shellscript
The -l string indicates a desire for the long-form directory listing,
in this case, listing only the directory entry for shellscript.
The output will be something like this:
-rwxr-xr-x 1 jones faculty 223 Feb 4 11:29 shellscript
This indicates that the access rights are rwxr-xr-x for this file. The first rxw applies to access by the owner, named jones, while the middle r-x applies to members of the group named faculty. The final r-x applies to all others.
The following script is useless but it illustrates a number of shell features.
#!/bin/tcsh
# shellscript text
echo entering $$ $1 $2
@ myvariable = $argv[1]
while ( $myvariable > 0 )
echo $argv[2]
@ myvariable = $myvariable - 1
shellscript $myvariable $argv[2]
end
echo exiting $$ $1 $2
Note that shell comments occur on lines starting with the # character. It is good form to document shell scripts just like any program, with a header indicating how to call it and what it does.
This shell script begins and ends with echo commands indicating entry and exit from the script. Text in the shell script starting with a dollar sign is replaced before that line of the script is interpreted. For example, $$ is replaced with the current process number, and $1 and $2 are replaced with the first and second arguments to the script.
The $1, $2 notation is shorthand for The $argv[1], $argv[2]. The short notation is the original Bourne shell notation. As the shell matured, named shell variables were added, and then these were divided into arrays of components.
The shell variable $myvariable is used to hold $argv[1]. This variable is initialized using the @ command. This command allows arithmetic expressions on the right-hand side of the assignment, while the otherwise similar set command does not allow arithmetic. The fact that the shell variable name is stripped of its leading dollar sign on the lefthand side of the assignment is ugly evidence of the evolution of the Unix shells.
All of the major Unix shells are general purpose programming languages. The example illustrates both iteration with a while loop and recursion. Note that the shell variables are local. Each invocation of a shell script launches a new shell with a completely new environment, based on the environment of the shell that launched it.
As a result, this number of times this script echoes $argv[2] is proportional to the square of the initial value of $argv[1].