A shell is a command line interpretor. It takes commands and executes them. As such, it
implements a programming language. The Bourne shell is used to create shell scripts -- ie.
programs that are interpreted/executed by the shell. You can write shell scripts with the C-
shell; however, this is not covered here.
Suppose you often type the command
and you'd rather type a simple command, say
Create a shell script
This quick example is far from adequate but some observations:
1. Shell scripts are simple text files created with an editor.
2. Shell scripts are marked as executeable
4. Should be located in your search path and ~/bin should be in your search path.
5. You likely need to rehash if you're a Csh (tcsh) user (but not again when you login).
6. Arguments are passed from the command line and referenced. For example, as $1.
All Bourne Shell scripts should begin with the sequence
From the man page for exec(2):
!"
#$%&'(
)*&
Comments are any text beginning with the pound (#) sign. A comment can start anywhere on
a line and continue until the end of the line.
All shell scripts should include a search path specifica- tion:
!"#$%%& !"#
A PATH specification is recommended -- often times a script will fail for some people
because they have a different or incomplete search path.
+&',,
A good shell script should verify that the arguments sup- plied (if any) are correct.
'(&
)*+,%-./.
+0
This script requires three arguments and gripes accordingly.
All Unix utilities should return an exit status.
12
'1.-1+-..(&
)*+345145
+0
!67
-
A non-zero exit status indicates an error condition of some sort while a zero exit status
indicates things worked as expected.
&'- !.
'
Exit codes are important for those who use your code. Many constructs test on the exit status
of a command.
+/
&
For example,
1&
894:;
Your code should be written with the expectation that others will use it. Making sure you
return a meaningful exit status will help.
Standard input, output, and error are file descriptors 0, 1, and 2. Each has a particular role and
should be used accordingly:
12
'1.-1+-..(&
)*+3451451
+0
761<1=6
>10>
-?
@&&
?
"&&
Error messages should appear on stderr not on stdout! Output should appear on stdout. As for
input/output dialogue:
<9A
1&
"9<B
/72&
55
BCDB?
E&
-&&
F@$55
F@$55
Note: this code behaves differently if there's a user to communicate with (ie. if the standard
input is a tty rather than a pipe, or file, or etc. See tty(1)).
For loop iteration
',,0/
<9
For example:
>G/HI>
<"/;!3
<
JJK
Alternatively you may see:
<9&&
•
Case
'
9
''C(?
&&(
For example:
515
'-.('-.(?
1$.L1M
1$>1.->
&&
'-.('-.('-.('-.(?
1$>1.->
&&
B?
)*+345145
+0
&&
•
Conditional Execution
+
'
(
For example:
'(&
)*+,%-./.
+0
Alternatively you may see:
&&'&(
•
While/Until Iteration
10
L9CM
For example:
61
9'(&
N
Alternatively you may see:
9&&
•
Variables
23
+,
4444
5,%046(,
o
Variable Assignment
",, ,7,/
!"#$%%& !"#
or
"/;!3$>O4>4>&?>
o
Exporting Variables
2 0
P@,I"<;QI G!3<<
'5;QI G!35$55(&
1&
5;QI G!3O>>%--?245&
;QI G!3
'5;QI G!35$55(&
;QI G!3$>>%--
;QI G!3
Likewise, for variables like the PRINTER which you want hon- ored by lpr(1).
From a user's .profile:
FQD"8F$ I& FQD"8F
Note: that the Cshell exports all environment variables.
o
Referencing Variables
84,% 49,:(,
@R<9
'5,I8F5$55(&
!"#$#/@8% !"#
!"#$%% !"#
The braces are required for concatenation constructs.
N-
The value of the variable "p_01".
LMN-
The value of the variable "p" with "_01" pasted onto the end.
o
Conditional Reference
o
L<9M
If the variable has been set, use it's value, else use word.
/I"ISFQ "$L /I"ISFQ " IM&
/I"ISFQ "
L<%9M
If the variable has been set and is not null, use it's value, else use word.
+,;
,,)
0%6(<1;5+=1,,
0
L<%29M
If variable is set use it's value, else print out word and exit. Useful for bailing
out.
o
Arguments
),/
-66
The command and arguments. With $0 the command and the rest the
arguments.
The number of arguments.
B6T
All the arguments as a blank separated string. Watch out for "$*" vs. "$@".
And, some commands:
Shift the postional variables down one and decrement number of arguments.
Set the positional variables to the argument list.
)/
9'(&
A use of the set command:
91
"/;!3$>O4>4>&?>
I //G
>G/HI>
<"/;!3
<
JJK
o
Special Variables
o
Current process id. This is very useful for constructing temporary files.
$-
5+5
+U
)
2
The exit status of the last command.
F
'2A-(
•
Quotes/Special Characters
'/
&*O?C:V)9
These are for command sequences, background jobs, etc. To quote any of these use a
backslash (\) or bracket with quote marks ("" or '').
>330+
%LM%C97E%RLMR
Double Quotes
>3 ,,%
(%?@3(+
'5LM5(&
$LMLMLM
Back Quotes
&03
'5>>5$55(&
$55
$545
$55
$55
and
"/;!3$>O4>4>&?>
•
Functions
!'
O?
L
M
For example:
1
NO?
L
1
'(&
%D1)*+
M
Within a function the positional parmeters $0, $1, etc. are the arguments to the
function (not the arguments to the script).
>
/
96
NO?
L
9N
M
7O?
'55$55(&
CN
N
•
Sourcing commands
"/
+'
/
. command
+/
F
What are the virtues of each? What's the difference? The second form is useful for
configuration files where environment variable are set for the script. For example:
#/I"#/I"I&
2
'LW!SX, #/@8ML#/I"M(&
LW!SX, #/@8ML#/I"M
Using configuration files in this manner makes it possible to write scripts that are
automatically tailored for differ- ent situations.
•
Test
+%6(
&
and (note the matching bracket argument)
'(&
On System V machines this is a builtin (check out the com- mand /bin/test).
&'- %0'(
A
8/
L96666M
is file writeable, readable, executeable, empty, etc?
LA666M+
are numbers equal, not equal, greater than, etc.?
L$6$M+
Are strings the same or different?
L6M+
Binary or; binary and; use ! for unary negation.
'1.-1+-..(&
)*+345145
+0
Learn this command inside out! It does a lot for you.
•
String matching
+,"
0
9'(&
B?$>C>&&
?&$&&
B?$>C>&&
?&$&&
B?,&&&
B?7$B&7&&
Of course getopt would work much better.
•
SysV vs BSD echo
&'- ! /
/72&
On SysV systems you'd say:
/724&
In an effort to produce portable code we've been using:
97
'5>>5$55(&
$55&$545
$55&$55
/72&
•
Is there a person?
+83
= $
8!3!
QR6
1&
894:;
The tradition also extends to output.
Q6<
1V*&
<$
<$
Beware: just because stdin is a tty that doesn't mean that stdout is too. User prompts
should be directed to the user terminal.
QR6
1&
894:;)*-
Have you ever had a program stop waiting for keyboard input when the output is
directed elsewhere?
•
Creating Input
>!/
7O?
'55$55(&
CN
N
alternatively, redirection from a file:
7O?
'55$55(&
NV
N
You can also construct files on the fly.
V
%
%VT99)
%
IY%I+
+,E,P/
A
8/E
Note: that variables are expanded in the input.
•
String Manipulations
!'0
"Q@8$>C+.>
"Q@8$>CRBBB4OB4?BB4R>
"Q@8$>C97RLKMR>
"Q@8$>4>4>&K>
"Q@8$>CO<91Z&?>
With some care, redefining the input field separators can help.
<Q
O?
L>QEI$55&>
K+
M
'(&
)*+,%1Q
+0
$>>
7VV8/EC55CRB$R
1$1
8/E
•
Debugging
+0/
1!;=0
- !;
!
,