sections in this module City College of San Francisco - CS160B
Unix/Linux Shell Scripting
Module: Scripting Basics1
module list

Commands Files vs. Shell Scripts

Your book refers to shell scripts and commands files interchangeably. We will be making a distinction in class. Both refer to a file of Unix commands. Whether we refer to them as a commands file or as a shell script depends on how those commands get executed.

Both commands files and shell scripts start as a file of Unix commands. Suppose we have such a file named mycmds in the current directory. To execute those commands we must give them to a shell.

One way to give them to a shell is to execute them in our current shell. This operation is called sourcing the commands file, or, in our terminology, using it as a commands file. The traditional way of sourcing a file of commands is to use the dot operator:

. ./mycmds

Because the dot operator can be difficult to see, an alternate method from the C shell has been adopted in bash. It replaces the dot operator with the word source:

source ./mycmds

hence the term "sourcing". The two techniques are identical. However, the source directive may not be available in other Bourne-type shells.

Those of you who are programmers can think of this as an include directive, and that is exactly what it is: the lines from mycmds are read and executed by your shell just as if you typed them in.

Let's see how this works. First, take a look at mycmds:

$ cat mycmds
echo "hello from mycmds"
NAME=Greg
cd /tmp
$

Before we start, here are a couple of pieces of information about our current environment:

$ echo $NAME

$ pwd
/home/gboyd
$

Now let's source mycmds

$ . ./mycmds
hello from mycmds

After sourcing mycmds, notice how our current environment has been modified:

$ echo $NAME
Greg
$ pwd
/tmp
$

The result was just as if we had typed the commands into the current shell. Our shell's environment (variables and current directory) were modified by the commands in mycmds. This can be useful in two instances:

Usually, modification of our shell's environment by commands from an external file is not desirable. In order to isolate our shell from the effects of the commands in our file we must execute those commands in a separate shell. You can do this in two ways:

bash < mycmds

This last mechanism is what we refer to as running a shell script. Let's see what is necessary to convert mycmds to a shell script

  1. First, add the interpreter directive. This first line tells the system how to execute your script. The line begins with #! as the first two characters on the line, followed by the path to the program that you want to interpret the file, in our case bash. The best path to use for bash is /bin/bash, so the first line should be 

#!/bin/bash

Note that the # must be at the beginning of the line.

  1. Next, make your program executable by adding x permission.
chmod +x mycmds
  1. Then execute it directly:
./mycmds

Here mycmds executes in a separate shell, isolating your shell's environment from any changes. The mycmds process is called the child shell (or subshell) and the shell that started mycmds is the parent shell.

Notice that while some extra preparation is needed before we can run mycmds as a shell script, the thing that decides whether it is a commands file or a shell script is how we run it. A shell script is executed directly. A commands file is read into the current shell. The same file can be used as both a shell script and a commands file.

Let's do the same experiment as before and execute the commands in mycmds as a shell script

$ ls -l mycmds
-rwx--x--x 1 gboyd users 55 Oct 13 12:36 mycmds
$ cat mycmds
#!/bin/bash
echo "hello from mycmds"
NAME=Greg
cd /tmp
$ echo $NAME

$ pwd
/home/gboyd
$ ./mycmds
hello from mycmds
$ echo $NAME

$ pwd
/home/gboyd
$

Variables and shell scripts

As you could see from the recent example, executing a file as a commands file (by sourcing it) is the same as typing the commands into your current shell. Thus, any variable set in the commands file becomes your variable. Additionally, if your commands file modifies a variable, your shell's environment is affected.

If you run the file as a shell script, things are very different. Since it runs in a separate process, variables are not shared. However, the child shell (the shell script) does get a copy of the environment variables of the parent shell when it starts. Still, these are separate variables! The copies in the child are simply initialized with the value of those in the parent.

Outputting messages from your shell script

As you know, your shell script can output a message using echo. echo outputs its arguments to standard output. When using echo, you should always enclose the output in some kind of quotes. We will discuss quoting rules in the next chapter. 

echo normally terminates its output by adding a newline character. If you want to suppress this behavior, add the -n option:

echo 'hello' ; echo 'there'

hello
there

echo -n 'hello ' ; echo 'there' # note the space after hello 

hello there

Temporary files

From time to time your shell script must create a temporary file. If your shell script is functioning in the real world you must ensure that any temporary file it creates cannot conflict with user files, and that you delete any temporary file you create after you are finished with it. One way to minimize any risk of conflict with user files is to encode your current process' process-id into the name of your temporary files. This has the added benefit of allowing multiple users to use your shell script at the same time, even if they are connected to the same directory. 

You can substitute the process id of the current shell process (your shell script) in a file name by using the $ variable. For example, if my pid is 4256, I could create a temporary file to hold the output of the command foo like this

foo > temp.$$

The real name of my temporary file would then be temp.4256. Before my shell script exits I could then remove my temporary file

rm -f temp.$$

Preview question: Can you explain the difference between local and environment variables? Which of the following variables are environment variables: SHELL, PWD, PS1, LOGNAME ?

Prev This page was made entirely with free software on linux:  
Kompozer
and Openoffice.org    
Next

Copyright 2011 Greg Boyd - All Rights Reserved.

Document made with Kompozer