Lab #9
CS 2351
UNIX Operating System

                                                                     Name _________________________________

                                                                                               Section ___________________

In this lab, you will learn about the Bourne shell and how to change to it. Shell scripts to be run in the Bourne shell will be developed and shell control statements used in the Bourne shell will be introduced. Control statements covered are: test, for, for in, if-then-else-fi, if-then-elif-fi, while, until, and case. Relational operators and expr used in the Bourne shell are introduced. A few errors you may encounter are discussed.

The Bourne shell was the first shell to be written. It does not have some of the features of the Korn shell or the C shell.  You cannot use the history commands or the command line editing like in the Korn shell. There are also no aliases available. You will not be able to use them while you are in the Bourne shell. This may be frustrating to you. One reason why you are looking at this shell, is that it is the main shell on all UNIX machines and not every machine will have the Korn shell.

You can change to another shell on your machine at any time by just typing in the name of that shell at the prompt. Type in:

                sh

What happened when you did this? ____________________________________________________

Your prompt should have changed. It should have something similar to ! $PWD >. Usually it would be a $ sign but you changed it for the Korn shell and so it will still be different for the Bourne shell. You will now be in the Bourne shell. If at some time you want to go back to the Korn shell, all you do is type in:

ctrl - d
   or
exit

You will then be returned to the Korn shell prompt. You must be in the Korn shell to log off of the computer.

First of all, lets make some special files in the bin directory for the chmod and printing for you to use when you are in the Bourne shell. Change to the bin directory. Type in:

                 cd bin

Next, type in:

                 ls -l

What files did you see listed? ____________________________________________________________

All of these special shell scripts work in the Korn shell but may not work in the Bourne shell. You are going to make both the change mode and the print shell scripts. In order to make the change mode file, call the file chb. Type this in the chb file:

#!/bin/sh
# Change mode command
# This file will make a file executable
echo "Read in name of file to be made executable: \c"
read filename
chmod u+x $filename
echo "$filename is now executable: "
ls -l $filename

Make this file executable. Try out the chk that you made before to see if it will work on this particular file. Did it work? __________________________________________________________________________

Make up another file called prnb. This file will allow you to type in the name of the file you want printed out without typing in the lp address every time you type it in. If you use some other printer more frequently, you would need to change the lp address. Type in the following:

#!/bin/sh
# This shell script will print a file in the Bourne shell
echo "Type in the name of the file to print out: \c"
read file
lp -dms108pr1 $file

Make this file executable also by using the chb file you just made.  Notice that on the first line of these programs there was the /bin/sh. The sh is for the Bourne shell. The Bourne shell also uses the echo statement instead of the print statement. Otherwise these two look very similar.

Usually any programs or shell scripts that you write in the Bourne shell will work automatically in the Korn shell. However, it does not necessarily work in the reverse order. If a program was written in the Korn shell, it will not necessarily work in the Bourne shell.

Go back to your Home directory. 

Now change to the lab4 directory. You will be using some files that you made in the lab4 directory. Type in:

                 pwd

What was the reply?______________________________________________________________

Flows of Control Structures

You will now be introduced to some control structures that are in the Bourne shell. Some of these will look similar to those you saw in the Korn shell. You will later learn about some control structures in the C shell. These are similar to the if-then-else type of statements you have used in other programming languages.

Test Command

The first control statement is called the test command. The test command evaluates an expression and returns a condition code indicating that the expression is either true (= 0) or false (not = 0).

It is used for branching. The one-branch if statement has a form of:

if (test command)
then
    commands
fi

The test command has many options that are available. A few of them are:

-f tests to see if filename listed is a file
-d tests to see if filename listed is a directory
-r tests to see if filename is a readable file
-w tests to see if filename is writeable
-x tests to see if filename is executable

Start a new shell script called sample1. Enter the following exactly as shown.

if (test -f books)
then
    ls
fi

Make sure that the "then" is on the second line. Notice that the control structure ends in "fi". This is "if" spelled backwards. You will work with other Bourne shell control structures later. These all end with the first word being spelled backwards.

After you have completed sample1, use the chb shell script that you made earlier. At the prompt, type in:

chb

You will be asked to "Read in name of file to be made executable". Type in:

sample1

You should then get a reply that "sample1" is now executable and it will list out the access codes for the file. The chb shell script can be used for other files that need to be made executable in this lab. Now type in:

sample1

This should run the sample1 shell script. What answer did you get? _________________________________________________________________________________

In the case of the single if statement, if the statement is true, the statement after the "then" is carried out. If it is not true, then nothing is done. Is the test condition true? ________________________

The two-branch if-statement is similar to the single-branch if-statement. Similar to the if then-clause, the else-clause must start on a new line. Use the vi editor and make this file called sample2. Enter the following exactly as shown:

if (test -d books)
then
    echo "books is a directory file"
else
    echo "books is a plain file with the \c"
    echo "following access permissions:"
    ls -l books
fi

Use the chb shell script to make this file executable and then type in:

sample2

Is the test condition true ?___________________________

What is printed ? ________________________________________________________________________________

Although you were not introduced to the test command in the Korn shell, it also works in that shell.

For shell control statement

The for structure has the following format:

for loop-index
do
    commands
done

In the For structure, the loop-index automatically takes on the value of each of the command line parameters, one at a time. It performs a series of commands involving each parameter in turn.

This is another shell control statement that can be used in the Bourne shell.

Use the interactive cat command (cat > <filename>) to create a file called tel that contains the following shell script. Remember, when you use the cat command, when you are done entering information, you finish with the ctrl - d.

for i
do
    grep -n $i telnos
done

Make this file executable by using  chb.  

Remember that the grep command is a search command that allows you to search for words or character matches in files. The shell script above will look for the list of arguments in the file telnos that are listed after the name of the shell script. In the example below, the tel is the name of the shell script and the let, lan, Bot, and Hal are arguments. Arguments are lists of information that you want. These are the patterns that will be searched for in the file telnos.

Now, issue the command:

tel let lan Bot Hal

What was the result? ________________________________________________________________

________________________________________________________________________________

________________________________________________________________________________

Next, issue the command:

tel MS MH

The grep command does a global search to find matching patterns. It must go through each line in an entire file to find the matches. This command can be very time consuming if you have a very large file. What was the result of the last search? ______________________________________________________________________

_______________________________________________________________________________

Now try the search:

tel \&

The backslash is required because the & is a special character which when appended to a command, indicates that the command is to run as a background process thereby leaving the terminal free to issue other commands. Here we wanted to search for the character &, hence the backslash. What was the result? _______________________________________________________________________________

For In

The For In structure has the following format:

for loop-index in argument-list
do
    <command list>
done

This structure assigns the value of the first argument in the argument list to the loop-index and executes the commands between the Do and the Done statements. The Do and Done statements mark the beginning and the end of the For loop. In order to see how this structure works, type in the following called name3:

for file in telnos*
do
    echo "==============================="
    echo "Sorted contents of $file"
    echo "==============================="
    sort -b +2 $file
    echo
done

Use the chmod shell script--chb to make the file executable. Type in the following to execute name3.

name3 | more

What was the output that you got from this control construct?

________________________________________________________________________________

________________________________________________________________________________

________________________________________________________________________________

Relational Operators used in the Bourne shell

Summary of Relational Operators

Operator Used to test:
= equality of two strings
!= inequality of two strings
-ne inequality of two integers
-lt true if integer on left is less than integer on right
-le true if integer on left is less than or equal to integer on right
-gt true if integer on left is greater than integer on right
-ge true if integer on left is greater than or equal to integer on right
-f true if a file is a plain file
-d true if a file is a directory
-a logical and - true if expresssion on left and right are both true
-o logical or - true if expresssion on left or right is true

Notice that these are different from the relational operators in the Korn shell.

If.. then .. else.. fi

The if-then-else clause can be used to cause execution of statements to occur if the specified test proves false. The general format of the if-then-else is:

if condition
then
    command
    command
else
    command
fi

If the result of the condition is true, then the commands enclosed between the then and else get executed. Otherwise, the statements between the else and fi will be executed.

If .. then .. elif .. else ..fi

The Elif statement combines the Else and If statements and allows you to construct a nested set of If Then Else structures. The format for this is:

if condition
then
    command
    command
elif
then
    command
    command
else
    command
    command
fi

You can use as many elifs as you want. At the end of it, you can place an else so that a set of commands can be executed if none of the preceding test expressions are true. Enter the following program called class2.

#!/bin/sh
#
# This program was written by: ( type your name here)
# This program will allow user to read in the number
# of hours a student has completed.
# It will then determine what classification the
# student is based on the hours completed.
#
#
echo "Read in number of hours a student has completed: \c"
read number
if [ $number -ge 1 -a $number -le 27 ]
then
    echo Class = Freshman
elif [ $number -gt 27 -a $number -le 60 ]
then
    echo Class = Sophomore
elif [ $number -gt 60 -a $number -le 93 ]
then
    echo Class = Junior
else
    echo Class = Senior
fi

Be sure to make the program executable using chb

Notice that you were to type in your name in the program. This is because you will later print this to the printer. Since all of the printouts look alike, you can tell which is yours by the name that is included in the program.

NOTE: when you enter this program, be sure to leave a space after the open bracket ([) and before the close bracket (]). If you do not leave a space between the brackets and other characters, you will get an error message. Also note that the if statement ends with the fi statement. The fi is if spelled backwards. Type in the following:

class2

At the prompt, enter a number. Execute the program several times using different numbers that fit in the different categories to test your shell control program.

Use the prnb shell script to print the program, class2 to the printer.

***********************************************************
                 Attach this file to your lab and turn it in with your lab.
***********************************************************

While

In the while structure, as long as the test-command returns a true exit status, the structure continues to execute the series of commands delimited by the Do and Done statements. Before each loop through the commands, the structure executes the test-command. When the exit status of the test-command is false, the structure passes control to the Done statement, and the shell continues to the next command. The While construct looks like this:

while test-command
do
    commands
done

Type in the following structure. Call it loop2.

count=1
while [ $count -le 10 ]
do
    echo "$count \c"
    count=`expr $count + 1`
done

NOTE: you need the back quotes when you use the expr command in this example.

What does the output of this script look like? _______________________________________________________________________________

How would you change this shell script, loop2, so that the numbers would be printed out on separate lines?   _______________________________________________________________________________

Arithmetic operators - Expr command

Notice that the expr command was used in the while structure. It evaluates an expression. It evaluates character strings that represent either numeric or nonnumeric values. Operators are used with the strings to form expressions.  The expr command returns an exit status of 0 (zero) if the expression is neither a null string nor the number 0, a status of 1 if the expression is null or 0, and a status of 2 if the expression is invalid.

The following examples show command lines that call expr to evaluate constants. You can also use expr to evaluate variables in a shell script. Type in the following examples and fill in the answers next to the expression:

expr 1 + 2 ___________
expr 5 "*" 10 ___________
expr 1+2 (no spaces between the 1 & 2) ___________
expr "5 * 10" ___________
count=100 ___________
expr $count + 1 ___________

Expr writes its results to the standard output. By using the backquote mechanism, you can assign expr's results to a shell variable:

result=`expr 1 + 2`
echo $result

These are just a few examples of how expr works. You can try other options or read more about it in the text.

Until

The until and while structures are very similar. They differ only in the sense of the test at the top of the loop. The until continues to loop until the test-command returns a true exit status. The while structure loops while the test-command continues to return a true or nonerror condition. The until structure is shown below:

until test-command
do
    commands
done

Type in the following structure. Call it numbers.

#!/bin/sh
read number
until [ $number -lt 0 ]
do
    echo $number
    echo "\c"
    number=`expr $number - 1`
done

Make this script executable and run it. You will see a blank line.  Type in  8 as the input value. What does the output of this script looks like?
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________

You will later be introduced to shell control statements in the C shell. There is no match for the Until in the C shell.

Case

The case structure provides a multiple branch decision mechanism. The case statement is similar to the switch statement in the C shell. The path that the structure chooses depends on a match between the test-string and one of the patterns. It is similar to the If-then-else command. The structure is as follows:

case test-string in
    pattern-1)
        command list;;
    pattern-2)
        command list;;
    pattern-N)
        command list;;
esac

Note that the end of the case statement is esac which is case spelled backwards.

Type in the following example. Name it choose2:

#!/bin/sh
# This program was written by: (your name here)
echo "Enter 1, 2, 3, or 4:\c"
read number
case $number in
    1)
        date;;
    2)
        ls;;
    3)
        pwd;;
    4)
        who | wc -l;;
    *)
        echo You have entered an incorrect value;;
esac

After you have completed this program, make it executable and try it out.

A Few Errors you may get using the Bourne Shell

If you are using an "if" statement in the Bourne shell, you could get an error such as this:

    <name of file>: syntax error at line7: `elif' unexpected

This means that you probably put the then statement on the same line with the "if" statement. You need to have the "then" statement on the next line as the first word on that line.

Another problem may be if you put a # (pound sign) in the first line without the #! /bin/sh. UNIX will assume that you want to run the program in the default login shell, which may not be the Bourne Shell.  If your defualt shell is not the Bourne shell, you may get an error when the script is executed. An example would be if you used the # sign in the first line of the program, choose2 above, you would get an error message:

        read: Command not found.
        number: Undefined variable.

Other errors occur when you add a space between the "=" (equal) sign when you are describing variables. You must not leave spaces on either side of an equal sign in the Bourne shell.

In order to get off the machine, you must type in:

exit
    or
ctrl -d

You will then be returned to the Korn shell and you can log off from there.

You should now have the following files in the directory, lab4:

telnos telnos2 telnos3 telnos4 telnos5
tel tel2 numbers 
sample1 sample2
name2 name3 choose choose2
class class2 loop loop2  

You should have the following files in the bin directory:

prn prnb
chk chkb
srch

05/27/03

Please indicate any parts of the lab that were hard to understand. 

_______________________________________________________________________________

_______________________________________________________________________________