Main index

Introducing UNIX and Linux


Processes and devices

Overview
Processes
      Process status
      Foreground and background
      Process control
      Signals
Environment
      Environment variables
      Global and local variables
      Executable scripts
Program control
      Job control
      Command history list
      Running a job at a specific time
      Running programs periodically
      Big programs
      Timing a program
      Running programs in order
Quotes and escapes
Devices
Backquotes
Summary
Exercises

Global and local variables

Suppose a process assigns a value to a variable. The value cannot be passed to the parent process, but may be passed to child processes. To illustrate this, consider a variable called X, which we set to be the number 42. Then invoke a second copy of the shell using sh; you will get the usual prompt, but this prompt is from the new shell, not from your login shell. The new shell is a child of your login shell. Now check the value of X, and you will see it is not assigned a value:

X=42
echo $X
42
sh
echo $X

(blank line)
$

The new value of X is not passed down to the child process. We say that the value of X is local to the process that assigned it the value, and no changes will be recognised by any child process. If you now cause the child shell to finish by typing ctrl-D, you will get the $ prompt again, this time from your login shell. Now, if you examine the value of X again, you will see that it is 42, as that was the value assigned to it in the login shell.

We can cause a variable instead to be global by means of the command export, which means that its value will be passed down to all the child processes, and their children, and so on. Do the same as in the example above, but immediately after setting X to 42, type a line exporting X:

export X

Worked example

Change your prompt from $ to enter command:
Solution: The variable PS1 contains the prompt; reset it and export its value:

PS1="enter command: "
enter command: export PS1

Another method for assigning a variable a value is by means of the command read. Followed by one or more variable names, this reads words from the standard input and assigns them to the successive variables. The following script requests the name of a user and sends them a greeting by mail:

echo "Whom do you wish to greet?"
read RECIPIENT
echo Hello | mailx -s Greeting $RECIPIENT

Generally you will read one variable at a time, but it is possible to read several at once from a single line of input. In this case you must be careful if the number of variables, and the number of words on the input line, are different. If there are fewer variables than words on the line, the initial variables will be assigned one word each, and the final one the rest of the line; if there are more variables than words on the line, the final variables will be assigned the null string. If script testread has the following contents:

read X Y Z
echo "X=$X Y=$Y Z=$Z"

then we might have the following:

sh testread
hello there chris
X=hello Y=there Z=chris
sh testread
hello
X=hello Y= Z=
sh testread
hello there chris jo and sam
X=hello Y=there Z=chris jo and sam

Worked example

Write a script to prompt the user for the name of a file and then print the file on their terminal.
Solution: Use echo to prompt the user, read to get a filename into a variable, and cat to display the file:

echo Type in a filename
read FILENAME
cat $FILENAME

One use of read that is not apparent from the above discussion is that it can be used to allow the user control over the speed with which a shell script is executed. Try creating a file (say cat2files) containing the following:

echo Type in 2 file names
read FILE1 FILE2
cat $FILE1
echo Press Return to continue
read X
cat $FILE2

Now execute that script - it will print out the first file on the screen, then pause for you to press Return before displaying the second file. The second read assigns a value to the variable X (which is not actually used for anything else), but waits for you to type in something before moving on to the next line.

Suppose file myprogram contains

echo The emperor is $MY_NAME

and you wish to run the commands in the file with MY_NAME set to a value. You could set MY_NAME, then export it, then run the file, so:

MY_NAME="Julius Caesar"
export MY_NAME
sh myprogram
The emperor is Julius Caesar

There is a problem with this, namely that you have reset MY_NAME in the current shell as well. You may not wish to do this. You may wish to test myprogram with the variable MY_NAME assigned a different value. This would be especially important if you were writing a script that used system-defined variables, such as TERM or LOGNAME, where it would be confusing if you were to reset them. You can use the following:

MY_NAME="Julius Caesar" sh myprogram
The emperor is Julius Caesar

This does not affect the current value of MY_NAME, but has the same effect as inserting the single line

MY_NAME="Julius Caesar"

at the start of the file myprogram. An equivalent effect can be achieved using the command env:

env MY_NAME="Julius Caesar" sh myprogram
The emperor is Julius Caesar


Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck