If
you have a basic familiarity with unix, and you have a lot of work
to do, then shell scripting can save you time. A shell script is
just a text file full of commands. It must be executable. Although
you may simply type in a bunch of commands that you would type at
the prompt, there are some more sophisticated things that you probably
have not done at the prompt (though you could). Different shells
have different options and different syntax available for doing
these more sophisticated things. This page will discuss bourne shell
scripts since they are easy, and fast. This
is just an introduction, you should look at the examples referenced
at the end and read books about shell scripting, and look on the
web to learn more.
The Simplest
Case
Here
is a very simple script. Create a file called fred and open
it in a text editor. Type
ls
-l
Save
the file. Make sure everyone can execute the file:
>chmod
ugo+x fred
Now
type:
>./fred
This
tells the shell to look in the current directory for fred and to
treat fred as a command. You should see that the results of running
fred are the same as running ls -l. Note, however, that unless fred
is in a directory specified in your path, that you will always have
to type the path to fred to run it.
You
can type multiple commands into a shell script, just put one command
on each line. Type some additions to fred (everything in red):
ls
-l
mkdir sally
cd sally
touch harry sydney veronica
Now
fred will tell you what files are in the current directory, then
make a directory named sally, cd into sally and make 3 files in
the directory (harry, sydney and veronica).
A
nice addition is to call the shell you want at the top of the script.
This just helps to prevent the script from blowing up if the system
calls some shell other than what you expect. Perhaps this is voodoo,
but it doesn't hurt anything and it tells you in the future which
shell language the script uses:
#!/bin/sh
ls-l
mkdir sally
cd sally
touch harry sydney veronica
This
script should do the same thing as it did before, but you have told
it explicitly to use the bourne shell. The very first line of the
script can be used for this sort of special call. You need not separate
the call to sh from the rest of the commands, but it makes it look
nicer.
Adding
Comments
When
you, or someone else, looks at your shell script in a year, it would
be nice if you knew what it did, who created, it, when, why, and
how to use it, simply by reading it. Good programmers make copious
comments explaining these things. Any line preceded by # (other
than the one that calls the interpreter, e.g., #!/bin/sh at the
top of the script), will be ignored by the interpreter:
#!/bin/sh
#The
above line calls sh to execute fred.
#fred
makes a directory named sally and creates 3 files in that #directory:
harry, sydney and veronica. 4/16/2002 DP.
#the
next line lists the files in the current directory
ls -l
#The
next line makes the directory "sally"
mkdir
sally
#The
next line cds into "sally"
cd sally
#The
following line uses the "touch" command to make the
files "harry", #"sydney" and "veronica".
touch harry sydney veronica
Positional
Arguments
In
the above script, there is only one way to change the names of the
directory or files that fred creates: open the script and modify
it.
But there is an alternative. You can use positional arguments. Positional
arguments are typed in order after the command. The shell knows
that the first word you type (e.g., fred) is the name of
the command. It thinks of this as $0. The first argument
to fred is $1. The next one is $2 etc. So, you could
do the following to allow a single argument to fred:
#!/bin/sh
#The
above line calls sh to execute fred.
#fred
makes a directory that you name at the command line
# and creates 3 files, harry, sydney and veronica, in that directory.
#4/16/2002 DP.
#The
next line makes the directory specified on the command line
mkdir
$1
#The
next line cds into that directory
cd $1
#The
following line uses the "touch" command to make the
files "harry", #"sydney" and "veronica".
touch harry sydney veronica
In
the above script, fred is allowed to take a single command line
argument, which it uses as a directory name. So if I type:
>fred
Mary
fred
will create a directory named Mary and put 3 files in it,
harry, sydney and veronica.
More
Positional Arguments
But
we could do even more:
#!/bin/sh
#The
above line calls sh to execute fred.
#fred
makes a directory that you name at the command line
# and creates 3 files, that you name at the command line, in that
directory.
#4/16/2002 DP.
#The
next line makes the directory
mkdir
$1
#The
next line cds into that directory
cd $1
#The
following line uses the "touch" command to make 3 files.
touch $2 $3 $4
Now
fred takes 4 arguments:
>fred
Office scott barb jen
The
above command creates an Office directory and fills it with
three files: scott, barb and jen. Although
you have to type more at the command line, the script is more generalized,
and thus more useful than our initial script.
Variable
Names
Sometimes,
you may want to repeat something over and over again in a script
(like a pathname) but you would prefer to type it once. Here's a
harmless example:
path="/data3/Dianne"
cd $path
pwd
This
will cd to the specified directory (/data3/Dianne) and print out
its location. As soon as the program ends, you will find yourself
back where you started.)
Or
a slightly different example:
path="/data3/Dianne"
cd $path"/temp"
pwd
This
is like the above, but it allows you to specify some general pathname
and then add to the path at the point of actually doing something.
Thus pwd will tell you that you are in /data3/Dianne/temp.
Self
Explanatory Scripts and If-Then Statements
If
we run one of our last two programs without the necessary arguments
(e.g., type fred Office scott), it will fail..and it won't
do a very good job of telling you why it failed. Maybe a clever
user would go find the script file and open it to read what it does...and
thus figure the problem out. But, the kind thing to do, as a programmer
is to provide a usage message, if the user goofs. Here is an example
of an if-then statement that creates such a usage message if a user
types fred without any arguments (or without enough arguments:
#!/bin/sh
#The
above line calls sh to execute fred.
#fred
makes a directory that you name at the command line
# and creates 3 files, that you name at the command line, in that
directory.
#4/16/2002 DP.
if
[ $# -lt 3 ]
then
echo "Usage: $0 filename filename filename"
echo "Example: $0 Mary f1 f2 f3"
echo "Comments: Create a directory (e.g., Mary) and fill
it with the named files (e.g., f1 f2 f3)"
exit 1
fi
#The
next line makes the directory
mkdir
$1
#The
next line cds into that directory
cd $1
#The
following line uses the "touch" command to make 3 files.
touch
$2 $3 $4
Explanation:
We have added an if-then statement. Let's examine it in detail.
It has the following structure:
if
x # if condition x is true
then #then do what comes on the next few lines, up until we
exit successfully
y #this is what you do if x is true
exit 1 #this says to exit the if-then statement with a value
of "1" (successful)
fi # this says the if-then statement is done
Here
"x" is a complex expression: [ $# -lt 3 ]. $#
means "number of arguments". -lt means "is
less than". So the statement reads: If the number of arguments
on the command line is less than 3.
"y"
is 3 echo statements. Echo statements simply write out their contents
to standard output (e.g., the screen).
For Loops
Looping
is a very valuable tool in scripts and programming. A loop does
something over and over again. A for loop does something over and
over again until it reaches the end of a list.
#!/bin/sh
#The
above line calls sh to execute fred.
#fred
makes a directory that you name at the command line
# and creates 3 files, that you name at the command line, in that
directory.
#4/16/2002 DP.
if
[ $# -lt 3 ]
then
echo "Usage: $0 filename filename filename"
echo "Example: $0 Mary f1 f2 f3"
echo "Comments: Create a directory (e.g., Mary) and fill
it with the named files (e.g., f1 f2 f3)"
exit 1
fi
#The
next line makes the directory
mkdir
$1
#The
next line cds into that directory
cd $1
#The
following line uses the "touch" command to make 3 files.
touch
$2 $3 $4
for
i in *
do
cp $i ..
done
Explanation:
This is an extremely simple for-loop that copies everything it finds
in the current directory up to the parent directory. Because we
have already moved into the directory we created (e.g., Office),
the for loop will find anything that meets the criterion (the criterion
is *, so our three files scott, barb and jen all match the
criterion). For each of these files, it'll assign it the variable
name i and run the procedures inside the the do-done statement
(in this case, copy that file up one level). Then it'll start the
for loop over again and do the next file. When it has operated once
on each file, it stops.
To see
some example scripts that use the above techniques, go here
and
click on any script name. You will see if-then statements embedded
in other if-then statements, and for loops that do weird things. As
with any other programming task, it is very useful to try work from
examples. You can find resources out on the net and in books devoted
to the subject. You
may also wish to see special notes on using backslashes
for line continuation.
|