Shell and Environment Variables

The shell allows you to store information in shell variables. Shell variables are all strings. There is no notion of "type" within the shell. Traditionally shell variables are named in all uppercase. However, in usual Unix style, both upper and lower case letters are allowed and the names are case sensitive. Many people use lowercase letters exclusively for the names of their shell variables.

To set a shell variable use an = sign immediately after the name. For example

$ NAME=Peter

If you put a space before the equals sign, the shell will think you are trying to run a program.

$ NAME =Peter
NAME: not found
$

You can get a list of all the shell variables currently defined with the set command. To remove the definition of a shell variable use the unset command. For example:

$ unset NAME
$

If you wish to use a shell variable (either in a script or at the command prompt) you must preceed it's name with a $. The $ causes the shell to expand the variable into its value. For example

$ NAME=Peter
$ echo NAME
NAME
$ echo $NAME
Peter
$

You can put other characters next to the name of a shell variable when you expand it provided the other characters could not possibly be part of the shell variable's name. For example

$ BACKUP=/home/pchapin/progs/backup.dir
$ cd $BACKUP/prog1
$

Here the shell knows the $ only applies to the text BACKUP. The / character must terminate the name of the shell variable.

If you want to put the expansion of a shell variable right next to other letters, you can enclose the name of the shell variable inside a {...} pair. For example

$ P=prog
$ cd ${P}1
$ pwd
/home/pchapin/prog1
$

The shell has numerous other features regarding the use of {...} in this context. For the sake of brevity, I will not discuss them here.

Normally when you run a program, the shell variables you've defined in your login shell are not present in the child program. Try defining a distinctive shell variable. Type set to verify its existence. Next, type sh at the prompt to run another shell. Type set to see that the shell variable you previously created is not present. Type exit to terminate the second shell.

The feature means that shell variables you create in scripts will not be present when the script terminates. This is because scripts are actually run in a child shell (exception: if you use the dot command, the script runs in the current shell. For example

$ . scriptfile

will cause shell variables introduced in scriptfile to exist after the script terminates).

In Unix, every process has an environment. The environment of a parent process is inherited by the child process. Thus information placed into the environment by the parent can be referenced by the child (but not visa versa). The shell allows you to name certain shell variables as environment variables. This is done with the export command.

$ NAME=Peter
$ export NAME
$

Now the shell variable NAME is part of the environment. It's value is accessible in child processes. To see what is part of your environment, type export alone at the prompt.

$ export
export TERM
export PATH
export EDITOR
$

Normally the PATH variable is part of the environment. This allows child shells to find commands the same was as the parent does. The TERM variable usually contains the name of the terminal you are using. This is used by child programs to manage the display. The EDITOR variable is often used by programs to locate a text editor. In this way you can use the editor of your choice with programs that need editor support.

There are several predefined shell variables that are set when you login or at other times. You can define any others you would like to use in your profile shell script (executed within the login shell before it prints the first prompt). Your profile login script is in the file .profile in your home directory.

Here is a list of the important predefined shell variables.

Table 3.1. Predefined Shell Variables

$HOMEThe absolute path to your home directory. By using this in a script many different users can execute the script and yet have distinct files created or processed. For example, a script might keep a configuration file in $HOME/config. This location is unique for every user.
$PATHColon separated list of directories to search for executable programs.
$CDPATHColon separated list of directories to search when the cd command is given a relative pathname.
$PS1The string used for the primary prompt.
$PS2The string used for the secondary prompt.
$?The status value returned by the last command. Whenever a command executes, it returns an integer to the shell. The meaning of that integer is defined by the command. The ? shell variable holds the integer. It changes after each command.
$$Process ID number of current shell. Useful for making temporary files in public space (like /tmp). Since no two processes have the same PID, embedding the PID of the current shell allows a script to keep it's temporary files separate from those of other programs.
$!Process ID number of last command launched in the background.
$1First argument to the script. Shell scripts can be invoked with arguments just like any other program. The arguments are called $1, $2, $3, etc.
$#The number of arguments given to the script.
$*A space delimited list of all the arguments given to the script.

This list is not complete.

Note that there exists a shift command that is very useful within scripts. It causes the value of $1 to be forgotten. The value of $2 is put into $1, the value of $3 is put into $2, and so forth. The value of $# is adjusted. Using this feature, a script can loop over all its command line arguments without concern for the exact number of such arguments. For example

# Inside a script file...
while [ $# -gt 0 ]
do
  # Process $1...
  shift
done

Even though the commands inside the loop process just $1, each argument is brought into $1 one at a time due to the shift.

Another technique for doing this is

# Inside a script file...
for ARG in $*
do
  # Process $ARG...
done