Unix/Linux Shell Programming
Instructor: Dr. Cheong Sio Tai, Victor
Macao Polytechnic Institute
Why
This is not a programming course! Why do we
bother to learn languages?
In system and network management, many
times you need to do some programming
Among those languages, for system administrators the
most common one is the shell programming
language.
Shell provides a simple, yet powerful, way for you to
interact with the system.
What
Basics of Linux Shell Programming
Control Statements
Command Lines
Linux Shell programming:
Shell scripts.
Definition.
Uses of shell scripts.
Writing shell scripts.
Shell scripts
A shell script is a text file with Unix commands
in it.
Shell scripts usually begin with a #! and a
shell name (complete pathname of shell).
Pathname of shell be found using the which
command.
The shell name is the shell that will execute this
script.
E.g: #!/bin/bash
Shell scripts (contd.)
If no shell is specified in the script file, the
default is chosen to be the currently executing
shell.
Shell scripts (contd.)
Any Unix command can go in a shell script
Commands are executed in order or in the flow
determined by control statements.
Different shells have different control
structures
The #! line is very important.
We will write shell scripts with the Bourne shell
(bash).
Shell scripts (contd.)
A shell script as a standalone is an executable
program:
Must use chmod to change the permissions of the
script to be executable also.
Can run script explicitly also, by specifying the
shell name.
E.g: $ bash myscript
E.g: $ csh myscript
Shell scripts (contd.)
Consider the example
$ bash myscript
Invokes the bash shell and then runs the script
using it.
Its almost as if we had the line #! /bin/bash in
the file myscript.
Similarly with the second example using csh.
myscript need not be an executable as bash is
running the script on its behalf.
Shell scripts (contd.)
Why write shell scripts ?
To avoid repetition:
If you do a sequence of steps with standard commands
over and over, why not do it all with just one command?
Or in other words, store all these commands in a file
and execute them one by one.
Shell scripts (contd.)
Why write shell scripts ?
To automate difficult tasks:
Many commands have subtle and difficult options that
you dont want to figure out or remember every time .
Simple Example
Assume that I need to execute the
following commands once in a while when
I run out of disk space:
rm -rf $HOME/.netscape/cache
rm -f $HOME/.netscape/his*
rm -f $HOME/.netscape/cookies
rm -f $HOME/.netscape/lock
rm -f $HOME/.netscape/.nfs*
rm -f $HOME/.pine-debug*
rm -fr $HOME/nsmail
Simple Example (contd.)
We can put all those commands into a
shell script, called myscript.
[wyli@linux14]$ cat myscript
#! /bin/bash
rm -rf $HOME/.netscape/cache
rm -f $HOME/.netscape/his*
rm -f $HOME/.netscape/cookies
rm -f $HOME/.netscape/lock
rm -f $HOME/.netscape/.nfs*
rm -f $HOME/.pine-debug*
rm -fr $HOME/nsmail
Sample Example (contd.)
To run the script:
Step 1:
Step 2:
$ chmod u+x myscript
Run the script:
$ ./myscript
Each line of the script is processed in order.
Shell scripts (contd.)
Shell variables:
Declared by:
varname=varvalue
To make them an environment variable, we
export it.
export varname=varvalue
Shell scripts (contd.)
Assigning the output of a command to a
variable:
Using backquotes, we can assign the output of
a command to a variable:
#! /bin/bash
filelist=`ls`
echo $filelist
Shell scripts (contd.)
Example:
[wyli@linux14]$ ls
a b c html/
[wyli@linux14]$ filelist=`ls`
[wyli@linux14]$ echo $filelist
a b c html/
[wyli@linux14]$
Shell scripts (contd.)
The expr command:
Calculates the value of an expression.
E.g:
[wyli@linux14]$ value=`expr 1 + 2`
[wyli@linux14]$ echo $value
3
[wyli@linux14]$
Notes on expr
Why do we need the expr command ???
E.g:
[wyli@linux14]$ file=1+2
[wyli@linux14]$ echo $file
1+2
[wyli@linux14]$
NOTE: 1+2 is copied as it is into val and not the result of
the expression, to get the result, we need expr.
Notes on expr
Variables as arguments:
[wyli@linux14]$ count=5
[wyli@linux14]$ count=`expr $count + 1`
[wyli@linux14]$ echo $count
6
[wyli@linux14]$
NOTE: count is replaced with its value by
the shell!
Notes on expr
expr supports the following operators:
arithmetic operators: +,-,*,/,%
comparison operators: <, <=, ==, !=, >=, >
boolean/logical operators: &, |
parentheses: (, )
precedence is the same as C, Java
Outline
Basics of Linux Shell Programming
Control Statements
Command Lines
Control statements
Without control statements, execution within a
shell scripts flows from one statement to the
next in succession.
Control statements control the flow of
execution in a programming language.
Control statements
The three most common types of control
statements:
conditionals: if/then/else, case, ...
loop statements: while, for, until, do, ...
branch statements: subroutine calls (good
programming practice), goto (usage not
recommended).
for loops
for loops allow the repetition of a command
for a specific set of values.
Syntax:
for var in value1 value2 ...
do
command_set
done
command_set is executed with each value of var
(value1, value2, ...) in sequence
Notes on for
Example: Listing all files in a directory.
#! /bin/bash
for i in *
do
echo $i
done
NOTE: * is a wild card that stands for all files in the
current directory, and for will go through each value
in *, which is all the files and $i has the filename.
Notes on for
Example output:
[wyli@linux14]$ chmod u+x listfiles
[wyli@linux14]$ ./listfiles
a
b
c
html
listfiles
[wyli@linux14]$
Conditionals
Conditionals are used to test something.
In Java or C, they test whether a Boolean variable
is true or false.
In a Bourne shell script, the only thing you can test
is whether or not a command is successful.
Conditionals
Every well behaved command returns back a
return code.
0 if it was successful
Non-zero if it was unsuccessful (actually 1..255)
This is different from C.
The if command
Simple form:
if decision_command_1
then
command_set_1
fi
The if command
Importance of having then on the next line:
Each line of a shell script is treated as one
command.
then is a command in itself
Even though it is part of the if structure, it is treated
separately.
Example
grep returns 0 if it finds something
returns non-zero otherwise
if grep unix myfile >/dev/null
then
echo "It's there"
fi
redirect to /dev/null so that
"intermediate" results do not get
printed
Using else with if
Example:
#! /bin/bash
if grep "UNIX" myfile >/dev/null
then
echo UNIX occurs in myfile
else
echo No!
echo UNIX does not occur in myfile
fi
Using elif with if
#! /bin/bash
if grep "UNIX" myfile >/dev/null
then
echo UNIX occurs in myfile
elif grep DOS myfile > /dev/null
then
echo DOS appears in myfile not UNIX
else
echo nobody is here in myfile
fi
Using colon in shell scripts
Sometimes, we do not want a statement to do
anything.
In that case, use a colon :
if grep UNIX myfile > /dev/null
then
:
fi
Does not do anything when UNIX is found in myfile .
The test command
Use for checking validity.
Three kinds:
Check on files.
Check on strings.
Check on integers
Notes on test
Testing on files.
test f file: does file exist and is not a directory?
test -d file: does file exist and is a directory?
test x file: does file exist and is executable?
test s file: does file exist and is longer than 0
bytes?
Example
#!/bin/bash
count=0
for i in *; do
if test x $i
then
count=`expr $count + 1`
fi
done
echo Total of $count files executable
NOTE: expr $count + 1 serves the purpose
of count++
Notes on test
Testing on strings.
test z string: is string of length 0?
test string1 = string2: does string1 equal string2?
test string1 != string2: not equal?
Example
#! /bin/bash
if test -z $REMOTEHOST
then
:
else
DISPLAY="$REMOTEHOST:0
export DISPLAY
fi
NOTE: This example tests to see if the value of
REMOTEHOST is a string of length > 0 or not,
and then sets the DISPLAY to the appropriate value.
Notes on test
Testing on integers.
test int1
test int1
test int1
test int1
test int1
int2 ?
test int1
int2 ?
eq int2: is int1 equal to int2 ?
ne int2: is int1 not equal to int2 ?
lt int2: is int1 less than to int2 ?
gt int2: is int1 greater than to int2 ?
le int2: is int1 less than or equal to
ge int2: is int1 greater than or equal to
Example
#!/bin/bash
smallest=10000
for i in 5 8 19 8 7 3
do
if test $i -lt $smallest
then
smallest=$i
fi
done
echo $smallest
NOTE: This program calculates the smallest among
the numbers 5, 8, 19, 8, 3.
Notes on test
The test command has an alias [].
Each bracket must be surrounded by spaces
#!/bin/bash
smallest=10000
for i in 5 8 19 8 7 3
do
if [ $i -lt $smallest ]
then
smallest=$i
fi
done
echo $smallest
The while loop
While loops repeat statements as long as the
next Unix command is successful.
Works similar to the while loop in C.
Example
#! /bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
sum=`expr $sum + $i`
i=`expr $i + 1`
done
echo The sum is $sum.
NOTE: The value of i is tested in the while to see if
it is less than or equal to 100.
The until loop
Until loops repeat statements until the next
Unix command is successful.
Works similar to the do-while loop in C.
Example
#! /bin/bash
x=1
until [ $x -gt 3 ]
do
echo x = $x
x=`expr $x + 1`
done
NOTE: The value of x is tested in the until to see if
it is greater than 3.
Outline
Basics of Linux Shell Programming
Control Statements
Command Lines
Command Line
Parameters to any program.
E.g:
$ ls t foo
-t and foo are parameters to the program ls.
The command line for ls now consists of these
three parameters: ls, -t and foo.
NOTE: command is also part of the command line
Command Line (contd.)
Shell scripts would not be very useful if we
could not pass arguments to them on the
command line.
Without arguments, restricts the usefulness of the
script.
Command Line (contd.)
Shell script arguments are numbered from
left to right
$1 - first argument after command.
$2 - second argument after command.
... up to $9.
They are called positional parameters.
Their position in the command line determines their
value.
Command Line (contd.)
Ex: find out if string appears in file.
Run command as: $ mystr string file
[wyli@linux14]$ cat mystr
#! /bin/bash
grep $1 $2
[wyli@linux14]$ ./mystr include err.c
# include <stdio.h>
[wyli@linux14]$
NOTE: $1 has value include and $2 has value err.c
Command Line (contd.)
Other variables related to arguments:
$0 Name of the command running.
$* All the arguments (even if there are more
than 9).
$# The number of arguments.
Command Line (contd.)
Example to use these special variables
[wyli@linux14]$ cat cmd_line
#! /bin/bash
echo "$0 is the name of the command"
echo "$* is the list of arguments"
echo "$# is the total number of arguments"
[wyli@linux14]$
Command Line (contd.)
Example output:
[wyli@linux14]$ ./cmd_line
./cmd_line is the name of the command
is the list of arguments
0 is the total number of arguments
[wyli@linux14]$ ./cmd_line 1 2 3 4 5
./cmd_line is the name of the command
1 2 3 4 5 is the list of arguments
5 is the total number of arguments
[wyli@linux14]$
Command Line (contd.)
Differences b/w C command line and shell
command line:
The command is not included in the list of
arguments.
The total number of arguments hence does not
include the command either.
More on bash variables
There are three basic types of variables in a
shell script:
Positional variables ...
Keyword variables ...
$1, $2, $3, ..., $9
Like $PATH, $HOME, and anything else we may define.
Special variables ...
Special bash variables
Special variables:
$! -- return process id of last background
process to finish
$? -- return status of last foreground
process to finish
$$ -- the process id of the current shell
There are others you can find out about with man
sh
Reading Input
All this while, we have talked about shell
scripts that do useful work and write some
output.
What about reading input ???
Done using the read command.
Reads one line of input and assigns it to variables
given as arguments.
Data type of variable does not matter, as shell has no
concept of data types.
Notes on read
Syntax:
read var1, var2, var3 .
Reads a line of input from standard input.
Assigns first word to var1, second word to var2, ...
The last variable gets any excess words on the
line.
Notes on read (contd.)
Example:
[wyli@linux14]$ read var1 var2 var3
this is to test the read
[wyli@linux14]$ echo $var1
this
[wyli@linux14]$ echo $var2
is
[wyli@linux14]$ echo $var3
to test the read
[wyli@linux14]$
NOTE: var3 has the rest of the string to test the read
Thanks