UNIX
© Copyright B. Brown, 1988-2000. All rights reserved. March
2000.
![]()
![]()
![]()
Assignment 3: Shell Programming
The objective of the
following exercises is to introduce you to shell programming. At
the end of these exercises you will be able to
Shell
Programming
Shell programming is using Unix commands to perform actions like
sorting, editing, re-arranging, merging and formatting files.
Commands are strung together to form miniature applications.
This module builds on the previous modules of [OS100] shell commands and the vi editor. During this module, you will use the shell commands to process files created with the vi editor. Handy access to the previous two modules will prove valuable in completing the various exercises scattered throughout this module.
Shell
Commands
The shell processes user commandsaccept
parametersbe executable programs which ordinary . These commands
can , or text files containing shell command lines (script files).
For script files, the shell spawns another instance of itself to read the file and execute the commands in it. This is known as a shell procedure.
The shell searches the shell variable path for finding commands. The shell uses a preset method of locating the command, by searching for the command in each of the following directories (in the order specified).
Shell
Variables
A variable is a name representing a string value. In this
example, the variable 'today' is assigned the value "Wednesday".
$ today="Wednesday"
User
Defined Shell Variables
The format for creating a shell variable is,
name=string
Consider the following example, which saves the current working directory (calculated by the command pwd) into the shell variable homedir.
$ homedir=`pwd`
To use the variable within the shell, it is preceded by a $. The following example uses the value stored in the shell variable homedir to switch directories.
$ cd $homedir
Predefined
Shell Variables
The shell uses a number of variables. Some of these are
| Variable | Meaning |
| HOME | name of users login directory |
| IFS | internal field separators |
| PATH | search path used for finding commands |
| PS1 | shell prompt |
The shell variables are printed out on the console screen by typing the keyword set.
Fill in the following table with your shell variable states (Hint, use the set command).
| Variable | Current Value |
| HOME | |
| PATH | |
| TERM | |
| PS1 |
Change the PS1 shell variable to the text string "hello ". Enter the command you used to do this in the space provided below.
..........................................................................
What happened to the UNIX prompt symbol?
..........................................................................
Reset the PS1 shell variable back to its original value, as a text string equal to what you found in the previous exercise and filled in the table on the previous page.
Shell
arguments and quotes
The shell supports pattern matching and recognition. The patterns
supported by the shell are,
| Argument | Meaning |
| * | Match all characters in a string |
| ? | Match a single character |
These matching characters (called wildcard characters) are used in the same way as other operating systems like MS-DOS. When you type a command, the shell program interprets symbols like the wildcard characters according to pre-defined rules. The following example lists all files ending in .dat in the current directory.
$ ls *.dat
data1.dat
text.dat
$
What is the command to list all the files in the current directory which begin with a . (period) character. Enter the command in the space provided below.
............................................
Does it work?? YES NO. If NO why do you think this might be so?
.
.
Other characters also have special meaning to the shell. These are interpreted according to special rules, and often lead to confusion, because of the way in which the shell interprets them.
< > * ? [ ]
To use these special characters as arguments to the shell, they are enclosed using single or double quotes.
For example, the following statement assigns the text string 'cp * $1' to the shell variable copyall.
$ copyall = 'cp * $1'
The contents are printed out by typing the command (this shows that the shell has created a new variable called copyall and set its value to the string cp * $1.
$ set
....
.
copyall=cp * $1
ignoreeof=10
$
Without the quotes around "cp * $1", the shell will try to execute the command 'cp * $1', rather than assign it to the new shell variable copyall. This means the copy command will be invoked to copy all files (*) to the filename specified in argument one ($1).
Type the command this time without quotes!
$ copyall=cp * $1
What is printed?
.
.
Within double quotes, the characters $, \, ` and " retain their special meaning to the shell. If you use these characters inside double quotes, the shell interprets them according to preset rules. To over-ride this, precede these characters with a backslash (\).
To examine this, consider the following example where the text string
The man said "hello".
is assigned to a shell variable. To assign this to a shell variable called string, the user types
$ string="The man said " hello "."
and the shell interprets this as equivalent to
"The man said" + hello + "."
as the second double quote is interpreted by the shell as finishing the text string. The shell thus interprets the word "hello" as a command, and tries to run it.
To prevent the shell from interpreting the second double quote as an end of string termination, it is preceded by a backslash.
$ string="The man said \" hello \"."
Typing set to now display the value of the shell variables reveals,
$ set
.....
....
string=The man said " hello ".
$
Complete the following table (HINT: assign each of the values to a shell variable, then use the set command to display the result, as in the previous examples).
| Input | Shell Interprets as |
| '`' | back quotation mark |
| one two | the string "one two" |
| "" | |
| "\"" | |
| "`" | |
| 'one * two" |
Shell
standard input and output
Most Unix commands do not care where their input is derived from,
or where their output is written. This feature allows commands to
work with files, devices, terminals and other commands.
There are three standard devices associated with a command when it executes.
| Device | Name | File Descriptor | Normally associated with |
| stdin | standard input | 0 | Keyboard |
| stdout | standard output | 1 | Console |
| stderr | standard error | 2 | Console |
Standard
Device Redirection Operators
In addition, the following characters have special meaning to the
shell, describing the origin of stdin and stdout
associated with a shell command. They are called redirection
operators.
Redirection is always used with files, never with other programs. Stdin can be redirected to read commands from a file instead of the keyboard, and stdout redirected to write to a file rather than the console screen.
| Symbol | Meaning |
| > | redirect stdout, create new |
| >> | append to stdout |
| < | redirect stdin |
The following example shows an example of redirecting stdin. The program sort normally reads from stdin, but in this example is instructed to read its input from the file input.dat (dont type the following command, it's only an example!)
$ sort < input.dat
Redirecting
stdout
The following example creates a file called user.log that
contains a list of the currently logged in users. Note that the
standard output for the who command has been
redirected from the terminal console to the file users.log.
In other words, the file users.log holds the output of
the command who, instead of the output being
displayed on the console screen. If the file users.log
already exists, it will be erased then created anew (Dont
type the following command, it's only an example!)
$ who > users.log
Redirecting
stderr
Error output from Unix commands is associated with file
descriptor 2, and by default goes to the console screen.
The following command redirects stderr for the executed command to a file called 'errors'. Note the use of the file descriptor preceding the redirection symbol (Dont type the following command, it's only an example!).
$ cc test.c 2>> errors
Note that the file descriptor precedes the redirection symbol without space or tab characters. The above example runs the UNIX C compiler on the source file test.c, and writes the error output to the file errors.
Pipelines
Pipes are a means of interconnecting commands together. The
output of one command becomes the input to another. Consider the
following example using redirection, using an intermediate file temp1
(dont type the following command, it's only an example!).
$ who > temp1
$ wc -l < temp1 > users
This example counts the number of users currently logged in, using a file called 'temp1'.
A pipe alternative is shown below. The two commands are connected via the pipe (a vertical bar, |), and this eliminates the need for the temporary file temp1 (dont type the following command, it's only an example!).
$ who | wc -l > users
Note that the following example is wrong!
$ who > wc -l > users
because programs can only be connected together via pipes.
What is the command pipeline you would use to search the output of who for a user called joe (HINT: Use the commands who and grep, connected via a pipe). Enter the actual command is the space provided below.
...........................................................................
Command
Substitution
Any command line can be placed within back quotation marks so
that the output of the command replaces the quoted command line
itself. This is known as command substitution.
The command or commands enclosed between the back quotation marks are first executed by the shell, then their output replaces the whole expression, back quotation marks included. This feature is most often used to assign shell variables.
$ today=`date`
In the above example, the command date returns the current date and time, which is then assigned to the shell variable today.
Consider the following examples. In the first example, the shell variable today is assigned the value date. In the second example, it is assigned the output of the program date, giving a different result.
$ today=date
$ set
today=date
$ today=`date`
$ set
today=Thursday 6th April, 1994
$
What is the command you would use to assign the output of the command pwd into the shell variable homedir. Write the actual command in the space provided below.
.................................................
Shell
Positional Parameters
When a shell is invoked, it creates positional parameters which
reflect the position of the arguments on the command line to be
processed. The name of the shell command (or script) is assigned
parameter $0, the next argument $1 and so on (Dont type
the following command, it's only an example!).
$ cp test1 test2 test3 test4
In this example, the command 'cp' is parameter $0, whilst 'test4' is parameter $4. There are four arguments to the program.
Predefined
Special Shell Variables
The following variables have special meanings, and are set ONLY
by the shell. They cannot be set by the user.
| Variable | Meaning |
| $# | Records the number of arguments passed to the shell,
not counting the first command. For example, cp a b c
sets $# to 3. One of its primary uses is to check that
enough arguments have been specified, if test $# -lt 2 then echo 'two or more args required'; exit fi |
| $? | Contains the exit status of the last command executed. Its value is a decimal string, and is usually zero for successful completion. |
| $$ | The process number of the current process, and is
unique. Often used to generate temporary filenames. temp=/usr/tmp/$$ ls > $temp |
| $! | The process number of the last process run in the background (using an &) and is a string of one to five digits. |
| $- | A string consisting of names of execution flags currently turned on in the shell. See the shell options 'xv' for more information. |
| $* | All the arguments given to the shell |
Shell
Conditional Tests
The test command evaluates the expression specified by the
arguments, and if true, returns a zero status, else it returns a
nonzero status.
| Test | Meaning |
| != | not equal |
| = | equal |
| -eq | equal |
| -gt | greater than |
| -ge | greater than or equal |
| -lt | less than |
| -le | less than or equal |
| ! | logic negation |
| -a | logical and |
| -o | logical or |
| -r file | true if the file exists and is readable |
| -w file | true if the file exists and is writable |
| -x file | true if the file exists and is executable |
| -s file | true if the file exists and its size > 0 |
| -d file | true if the file is a directory |
| -f file | true if the file is an ordinary file |
| -t filed | true if the file descriptor is associated with a terminal |
| -n str | true if the length of str is > 0 |
| -z str | true if the length of str is zero |
Consider the following shell script example.
#test to see if only one argument is passed to the shell script
if test $# != 1
then
echo "You must supply one argument"; exit
fi
What is the sequence of commands you would use to test for two or more arguments? Enter the command sequence in the space provide below.
..........................................................................
..........................................................................
..........................................................................
..........................................................................
..........................................................................
What is the sequence of commands you would use to test if argument $1 was a directory? Enter the command sequence in the space provide below.
..........................................................................
..........................................................................
..........................................................................
..........................................................................
..........................................................................
#test to see if the argument is a file
if test $# != 1
then
echo "You must supply one argument"; exit
fi
if test -f $1
then
echo "$1 is a file"
else
echo "$1 is not a file"
fi
#test to see if the argument exists, is a file or directory
if test $# != 1
then
echo "You must supply one argument"; exit
fi
if test -d $1
then
echo "$1 is a directory"
else
if test -f $1
then
echo "$1 is a file"
else
echo "$1 does not exist"
fi
fi
REVIEW
TEST
Answer all questions below before proceeding. Place your answers
in the spaces provided.
Which shell character matches a single character?
..................................................
State the three standard devices associated with shell procedures.
.............. .............. ...............
Rewrite the following command so that it executes correctly.
who | users.log ............................................
Write a command that assigns the system date to the shell variable PS1.
.................................................
The Shell
State
The state of the shell at any given instance includes the values
of positional variables, user defined variables, environment
variables, modes of execution and the current working directory.
Often, the user requires to change the working directory within the shell. This can be done without affecting the original shell by enclosing the command in parenthesis.
(cd /etc; cp passwd /usr/joe/passwd)
The shell also reads the .profile file stored in the users home directory when the user first logs in. This file specifies the state of various shell variables. The next module will explain in detail the significance of this file.
Shell
Execution Flags
The set command is used to alter the behaviour of the shell by
altering two flags.
| Shell Flag | Effect |
| -v | Input lines are printed as they are read by the shell. Commands are executed after the line is printed. |
| -x | Commands and their arguments are printed as they are executed. Shell control commands (like for, while) are not printed. Displays a trace of only the commands actually executed by the shell. |
The flags are turned off by typing
$ set +xv
To list the shell variables which are exported external to the shell, type
$ export
To get a list of the shell variables, type
$ printenv
or
$ env
![]()
![]()
![]()
Home | Other Courses | Assessments | Notes | Tests
© Copyright Brian Brown, 1988-2000. All rights reserved.