Main index

Introducing UNIX and Linux


More on shells

Overview
Simple arithmetic
      Arithmetic expansion
            Operators for arithmetic expansion
      The 'expr' command
Pattern matching
      Patterns
            Examples of patterns
      The case statement
Entering and leaving the shell
More about scripts with options
Symbolic links
Setting up terminals
Conventions used in UNIX file systems
Summary
Exercises

Entering and leaving the shell

In this section we look at the command sh - the shell. As we have discussed, the shell is a program. It is treated just as any other utility, and as such can take arguments. If it takes one filename as its argument, the action taken is to take its input (the commands for that shell) from that file, which is called a shell script. With no arguments, the shell reads its commands from the standard input. When a shell terminates, just like any other command it returns an exit status, which is normally the status of the last command executed by that shell. Create a file (mycommand, say), containing a single line which is the shell command false. Run the command and check its exit status using $?:

sh mycommand
echo $?
1

Add an extra line, which is the shell command true, to the end of mycommand (using vi or >>) which is the shell command true; run the command again and check the exit status. This time it will be 0.

A shell can be forced to terminate with a specific exit status by means of command exit. It is good practice explicitly to use exit to leave a script, rather than allowing a default exit status. Add the following line to the end of mycommand, run it again and see what exit status you then get:

exit 42

Any commands that might be executed after an exit command are discarded; exit kills the shell immediately. The same is true of an interactive shell.

Type sh to start a new interactive shell, and reset the prompt (so you know which is the new shell, and which the previous one) then type exit followed by a number. You will see that the new shell terminates (since you are back to the original prompt), and $? confirms that the new shell did indeed return an exit status to the original shell.

sh
PS1="--> "
--> exit 99
echo $?
99

Worked example

Write a script called morning to exit with exit status 0 (if it is run before noon) and status 1 (if run after noon).
Solution: Use date to check the time, then test to check whether the time is am or pm.

HOUR=$( date +"%H" )   # HOUR is a number between 0 and 23
if   [ $HOUR -le 11 ]  # Check HOUR is AM
then exit 0            # ... then exit with status 0
else exit 1            # ... otherwise status 1
fi

This command can then be used, for instance, in the following manner:

if sh morning
then echo "Good morning"
else echo "Good afternoon"
fi

You could have piped the output from date to cut instead of using the formatting option to date, as in previous worked examples. By now, however, you should be getting into the habit of using man to find out more information on commands.

The shell supports various options, just like other commands. A very useful option is -x ('eXpand'), which instructs the shell that, each time it is about to execute a command, it should display on the standard error stream the name of that command. This is performed after all variable names have been replaced by their values, and other substitutions done; it is thus a very good method of debugging shell scripts in the event of them not working as planned. For instance, supposing file badcommand contains:

date           # This is OK ...
cat $LOGNAME   # but file chris doesn't exist

We could then run this with option -x set:

sh -x badcommand
+ date
Mon Dec 10 17:39:52 GMT 2001
+ cat chris
cat: chris: No such file or directory

Shell options can be set during a shell session by means of the command set:

set -x

and can be unset as follows:

set +x

Within a script - or indeed when using an interactive shell - you can set the positional parameters $1, $2, etc., without passing them as arguments to the script. This uses set, and in the same way as before. Suppose we have a file testfile, which contains a script. Having set -x at the start of the file and executing the file using sh would be equivalent to not having set -x in the script, and running the script with sh -x testfile. If we wanted to pass other arguments to testfile, we could either have:

sh testfile arg1 arg2 arg3

or we could set the extra arguments at the start of the script with

set arg1 arg2 arg3

in which case $1 would become arg1, $2 would become arg2, $3 would become arg3 and $# would become 3. This is handy when debugging scripts that use positional parameters. After setting positional parameters, you can list what they are, together with the values of all other environment variables, by just typing set. You can unset all of them with:

set --

Try the following:

set --
set Chris
echo Hello $1
Hello Chris
set Sam
echo Hello $1
Hello Sam

The line set Sam has reset the value of the first positional parameter $1 to Sam.


Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck