CHAPTER 7:
SHELL PROGRAMMING
AUTOMATING TASKS:
Agenda
What is a shell? A shell script?
Introduction to bash
Running Commands
Shell Structures
Applied Shell Programming
Introduction to Shell Programming
Computers understand the language of 0's and 1's called
binary language.
In early days of computing, instructions are provided using
binary language, which is difficult for all of us, to read and
write. So in Os there is special program called Shell. Shell
accepts your instructions or commands in English (mostly)
and if its a valid command, it is passed to kernel.
Introduction to Shell Programming
Shell is a user program or it's a environment provided for
user interaction.
Shell is an command language interpreter that executes
commands read from the standard input device (keyboard)
or from a file.
4
UNIX Command Interpreters
Linux has a variety of different shells:
Bourne shell (sh), C shell (csh), Korn shell (ksh), TC shell (tcsh),
Bourne Again shell (bash).
Certainly the most popular shell is “bash”. Bash is an sh-
compatible shell
To find all available shells in your system type following
command: $ cat /etc/shells
5
Programming or Scripting ?
bash is not only an excellent command line shell, but a scripting language in itself. Shell
scripting allows us to use the shell's abilities and to automate a lot of tasks that would
otherwise require a lot of commands.
Difference between programming and scripting languages:
Programming languages are generally a lot more powerful and a lot faster than
scripting languages. Programming languages generally start from source code and are
compiled into an executable. This executable is not easily ported into different operating
systems.
A scripting language also starts from source code, but is not compiled into an
executable. Rather, an interpreter reads the instructions in the source file and executes
each instruction. Interpreted programs are generally slower than compiled programs.
The main advantage is that you can easily port the source file to any operating system.
bash is a scripting language. Other examples of scripting languages are Perl, Lisp, and
Tcl.
What is Shell Script
Normally shells are interactive. It means shell accepts
commands from you (via keyboard) and execute them.
But if you use commands one by one (sequence of 'n'
number of commands), the you can store this
sequence of commands to text file and tell the shell to
execute this text file instead of entering the commands.
This is known as a shell script.
Shell script defined as:
"A Shell Script is a series of commands written in plain
text file. Shell script is just like batch file is MS-DOS but
have more power than the MS-DOS batch file."
7
Shell Program Structure
A shell program contains high-level programming
language features:
–Variables for storing data
–Decision-making control (e.g. if and case statements)
–Looping abilities (e.g. for and while loops)
–Function calls for modularity
8
Steps to Create Shell Programs
Specify shell to execute program
–Script must begin with #! to identify shell to be
executed
Examples:
#! /bin/sh (defaults to bash)
#! /bin/bash
#! /bin/csh
#! /usr/bin/tcsh
Make the shell program executable
–Use the “chmod” command to make the
program/script file executable
9
How to write shell script
(1) Use any editor like vi or pico, gedit to write shell script.
(2) After writing shell script set execute permission for your
script as follows
syntax: chmod permission your-script-name
$ chmod +x your-script-name OR $ chmod 755 your-script-name
This will set read write execute (7) permission for owner, for
group and other permission is read and execute only (5).
(3) Execute your script as syntax:
bash your-script-name
sh your-script-name
./your-script-name
$ bash bar
$ sh bar
$ ./bar
10
Basic Shell Programming
A script is a file that contains
shell commands
data structure: variables
control structure: sequence, decision, loop
Input
prompting user
command line arguments
Decision:
if-then-else
case
Repetition
do-while, repeat-until
for
select 11
What is a Shell Script? What To Do
vi hello.sh
#!/bin/sh
echo ‘Hello, world’
% chmod +x hello.sh
% ./hello.sh
Hello, world
What is a Shell Script? Executable
vi hello.sh
#!/bin/sh
echo ‘Hello, world’
% chmod +x hello.sh
% ./hello.sh
Hello, world
What is a Shell Script? Running it
vi hello.sh
#!/bin/sh
echo ‘Hello, world’
% chmod +x hello.sh
% ./hello.sh
Hello, world
FORMATTING SHELL PROGRAMS
Comments
Start comment lines with a pound sign (#)
Include comments to describe sections of your program
Help you understand your program when you look at it
later
15
Single and Double Quote
When assigning character data containing spaces or special characters, the data
must be enclosed in either single or double quotes.
Using double quotes to show a string of characters will allow any variables in the
quotes to be resolved
$ var=“test string”
$ newvar=“Value of var is $var”
$ echo $newvar
Value of var is test string
Using single quotes to show a string of characters will not allow variable
resolution
$ var=’test string’
$ newvar=’Value of var is $var’
Command Substitution
The backquote “`” is different from the single quote “´”. It is used for command substitution:
`command`
$ LIST=`ls`
$ echo $LIST
hello.sh read.sh
We can perform the command substitution by means of $(command)
$ LIST=$(ls)
$ echo $LIST
hello.sh read.sh
$ rm $( find / -name “*.tmp” )
The export command
The export command puts a variable into the environment so it will be accessible
to child processes. For instance:
$ x=hello
$ bash # Run a child shell.
$ echo $x # Nothing in x.
$ exit # Return to parent.
$ export x
$ bash
$ echo $x
hello # It's there.
If the child modifies x, it will not modify the parent’s original value. Ver ify this by
changing x in the following way:
The Environment
The Unix system is controlled by a number of shell variables that are
separately set by the system some during boot sequence, and some
after logging in. These variables are called system variables or
environment variables.
The set statement displays the complete list of all these variables. Built-
in variable names are defined in uppercase.
19
The Environment
The PATH : is a variable that instructs the shell about the route it should
follow to locate any executable command.
The HOME : when you log in, UNIX normally places you in a directory
named after your login name.
The SHELL: determines the type of shell that a user sees on logging in.
.bash_profile : the script executed during login time. Every time you
make changes to it, you should log out and log in again.
The .bash_profile must be located in your home directory, and it is
executed after /etc/profile, the universal profile for all users. Universal
environment settings are kept by the administrator in /etc/profile so that
they are available to all users. 20
Bash Shell
The Environment
ALIASES : it allows you to assign short-hand names for commands you
may be using quite frequently. This is done with the alias statement.
Consider following ex.
– $ alias l=‘ls -l’
Aliases are listed when the alias statement is used without argument.
The alias feature also allows you to incorporate positional parameters as
variables in an alias.
For ex.
– $ alias showdir=‘cd $1 ; ls -l’
When you want to see the contents of the directory /home/arm
21
Environmental Variables
There are two types of variables:
Local variables
Environmental variables
Environmental variables are set by the system and can usually be found by using the env
command. Environmental variables hold special values. For instance:
$ echo $SHELL
/bin/bash
$ echo $PATH
/usr/local/bin:/bin:/usr/bin
Environmental variables are defined in /etc/profile, /etc/profile.d/ and ~/.bash_profile.
These files are the initialization files and they are read when bash shell is invoked.
Environmental Variables
HOME: The default argument (home directory) for cd.
PATH: The search path for commands. It is a colon-separated list of directories that
are searched when you type a command.
LOGNAME: contains the user name
HOSTNAME: contains the computer name.
Usually, we type in the commands in the following way:
$ ./command
By setting PATH=$PATH:. our working directory is included in the search path for
commands, and we simply type:
$ command
If we type in
$ mkdir ~/bin
Read command
The read command allows you to prompt for input and store it in a variable.
Example:
#!/bin/bash
echo -n “Enter name of file to delete: ”
read file
echo “Type 'y' to remove it, 'n' to change your mind ... ”
rm -i $file
echo "That was YOUR decision!”
Line 2 prompts for a string that is read in line 3. Line 4 uses the interactive
remove (rm -i) to ask the user for confirmation.
Variables
We can use variables as in any programming languages. Their values are
always stored as strings, but there are mathematical operators in the shell
language that will convert variables to numbers for calculations.
We have no need to declare a variable, just assigning a value to its reference
will create it.
Example
#!/bin/bash
STR=“Hello World!”
echo $STR
Line 2 creates a variable called STR and assigns the string "Hello World!" to it.
Then the value of this variable is retrieved by putting the '$' in at the beginning.
Warning !
The shell programming language does not type-cast its variables. This means
that a variable can hold number data or character data.
count=0
count=Sunday
Switching the TYPE of a variable can lead to confusion for the writer of the script
or someone trying to modify it, so it is recommended to use a variable for only a
single TYPE of data in a script.
Examples: Command Line Arguments
% set tim bill ann fred
$1 $2 $3 $4
% echo $* The ‘set’
tim bill ann fred command can
% echo $# be used to
4 assign values to
% echo $1
positional
parameters
tim
% echo $3 $4
ann fred
27
Arithmetic Evaluation
The let statement can be used to do mathematical functions:
$ let X=10+2*7
$ echo $X
24
$ let Y=X+2*4
$ echo $Y
32
An arithmetic expression can be evaluated by $[expression] or $((expression))
$ echo “$((123+20))”
143
$ VALORE=$[123+20]
Arithmetic Evaluation
Available operators: +, -, /, *, %
Example
$ cat arithmetic.sh
#!/bin/bash
echo -n “Enter the first number: ”; read x
echo -n “Enter the second number: ”; read y
add=$(($x + $y))
sub=$(($x - $y))
mul=$(($x * $y))
div=$(($x / $y))
mod=$(($x % $y))
# print out the answers:
echo “Sum: $add”
Conditional Statements
Conditionals let us decide whether to perform an action or not, this decision is
taken by evaluating an expression. The most basic form is:
if [ expression ];
then
statements
elif [ expression ];
then
statements
else
statements
fi
the elif (else if) and else sections are optional
Expressions
An expression can be: String comparison, Numeric comparison, File operators
and Logical operators and it is represented by [expression]:
String Comparisons:
= compare if two strings are equal
!= compare if two strings are not equal
-n evaluate if string length is greater than zero
-z evaluate if string length is equal to zero
Examples:
[ s1 = s2 ] (true if s1 same as s2, else false)
[ s1 != s2 ] (true if s1 not same as s2, else false)
Expressions
Number Comparisons:
-eq compare if two numbers are equal
-ge compare if one number is greater than or equal to a number
-le compare if one number is less than or equal to a number
-ne compare if two numbers are not equal
-gt compare if one number is greater than another number
-lt compare if one number is less than another number
Examples:
[ n1 -eq n2 ] (true if n1 same as n2, else false)
[ n1 -ge n2 ] (true if n1greater then or equal to n2, else false)
[ n1 -le n2 ] (true if n1 less then or equal to n2, else false)
Relational Operators
Meaning Numeric String
Greater than -gt
Greater than or equal -ge
Less than -lt
Less than or equal -le
Equal -eg = or ==
Not equal -ne !=
str1 is less than str2 str1 < str2
str1 is greater str2 str1 > str2
String length is greater than zero -n str
String length is zero -z str
33
Examples
$ cat user.sh
#!/bin/bash
echo -n “Enter your login name: "
read name
if [ “$name” = “$USER” ];
then
echo “Hello, $name. How are you today ?”
else
echo “You are not $USER, so who are you ?”
fi
$ cat number.sh
#!/bin/bash
echo -n “Enter a number 1 < x < 10: "
read num
if [ “$num” -lt 10 ]; then
if [ “$num” -gt 1 ]; then
Expressions
Files operators:
-d check if path given is a directory
-f check if path given is a file
-e check if file name exists
-r check if read permission is set for file or directory
-s check if a file has a length greater than 0
-w check if write permission is set for a file or directory
-x check if execute permission is set for a file or directory
Examples:
[ -d fname ] (true if fname is a directory, otherwise false)
[ -f fname ] (true if fname is a file, otherwise false)
[ -e fname ] (true if fname exists, otherwise false)
Example
#!/bin/bash
if [ -f /etc/fstab ];
then
cp /etc/fstab .
echo “Done.”
else
echo “This file does not exist.”
exit 1
fi
Exercise.
Write a shell script which:
– accepts a file name
– checks if file exists
Expressions
Logical operators:
! negate (NOT) a logical expression
-a logically AND two logical expressions
-o logically OR two logical expressions
Example:
#!/bin/bash
echo -n “Enter a number 1 < x < 10:”
read num
if [ “$num” -gt 1 -a “$num” -lt 10 ];
then
echo “$num*$num=$(($num*$num))”
Bash Shell
Expressions
Logical operators:
&& logically AND two logical expressions
|| logically OR two logical expressions
Example:
#!/bin/bash
echo -n "Enter a number 1 < x < 10: "
read num
if [ “$number” -gt 1 ] && [ “$number” -lt 10 ];
then
echo “$num*$num=$(($num*$num))”
else
Example
$ cat iftrue.sh
#!/bin/bash
echo “Enter a path: ”; read x
if cd $x; then
echo “I am in $x and it contains”; ls
else
echo “The directory $x does not exist”;
exit 1
fi
Shell Parameters
Positional parameters are assigned from the shell’s argument when it is invoked.
Positional parameter “N” may be referenced as “${N}”, or as “$N” when “N”
consists of a single digit.
Special parameters
$# is the number of parameters passed
$0 returns the name of the shell script running as well as its
location in the file system
$* gives a single word containing all the parameters passed
to the script
$@ gives an array of words containing all the parameters
passed to the script
$ cat sparameters.sh
#!/bin/bash
Trash
$ cat trash.sh
#!/bin/bash
if [ $# -eq 1 ];
then
if [ ! –d “$HOME/trash” ];
then
mkdir “$HOME/trash”
fi
mv $1 “$HOME/trash”
else
echo “Use: $0 filename”
exit 1
fi
Case Statement
Used to execute statements based on specific values. Often used in place of an
if statement if there are a large number of conditions.
Value used can be an expression
each set of statements must be ended by a pair of semicolons;
a *) is used to accept any value not matched with list of values
case $var in
val1)
statements;;
val2)
statements;;
*)
statements;;
Example 1 (case.sh)
$ cat case.sh
#!/bin/bash
echo -n “Enter a number 1 < x < 10: ”
read x
case $x in
1) echo “Value of x is 1.”;;
2) echo “Value of x is 2.”;;
3) echo “Value of x is 3.”;;
4) echo “Value of x is 4.”;;
5) echo “Value of x is 5.”;;
6) echo “Value of x is 6.”;;
7) echo “Value of x is 7.”;;
8) echo “Value of x is 8.”;;
9) echo “Value of x is 9.”;;
Example 2: The case Statement
#!/bin/bash
echo "Enter Y to see all files including hidden files"
echo "Enter N to see all non-hidden files"
echo "Enter q to quit"
read -p "Enter your choice: " reply
case $reply in
Y|YES) echo "Displaying all (really…) files"
ls -a ;;
N|NO) echo "Display all non-hidden files..."
ls ;;
Q) exit 0 ;;
*) echo "Invalid choice!"; exit 1 ;;
esac
45
Example 3: The case Statement
#!/bin/bash
ChildRate=3
AdultRate=10
SeniorRate=7
read -p "Enter your age: " age
case $age in
[1-9]|[1][0-2]) # child, if age 12 and younger
echo "your rate is" '$'"$ChildRate.00" ;;
# adult, if age is between 13 and 59 inclusive
[1][3-9]|[2-5][0-9])
echo "your rate is" '$'"$AdultRate.00" ;;
[6-9][0-9]) # senior, if age is 60+
echo "your rate is" '$'"$SeniorRate.00" ;;
esac
46
Repetition Constructs
47
Iteration Statements
The for structure is used when you are looping through a range of variables.
for var in list
do
statements
done
statements are executed with var set to each value in the list.
Example
#!/bin/bash
let sum=0
for num in 1 2 3 4 5
Iteration Statements
#!/bin/bash
for x in paper pencil pen
do
echo “The value of variable x is: $x”
sleep 1
done
if the list part is left off, var is set to each parameter passed to the script ( $1, $2,
$3,…)
$ cat for1.sh
#!/bin/bash
for x
do
echo “The value of variable x is: $x”
sleep 1
Example (old.sh)
$ cat old.sh
#!/bin/bash
# Move the command line arg files to old directory.
if [ $# -eq 0 ] #check for command line arguments
then
echo “Usage: $0 file …”
exit 1
fi
if [ ! –d “$HOME/old” ]
then
mkdir “$HOME/old”
fi
echo The following files will be saved in the old directory:
echo $*
for file in $* #loop through all command line arguments
Example (args.sh)
$ cat args.sh
#!/bin/bash
# Invoke this script with several arguments: “one two three“
if [ ! -n “$1” ]; then
echo “Usage: $0 arg1 arg2 ..." ; exit 1
fi
echo ; index=1 ;
echo “Listing args with \”\$*\”:”
for arg in “$*” ;
do
echo “Arg $index = $arg”
let “index+=1” # increase variable index by one
done
echo “Entire arg list seen as single word.”
echo ; index=1 ;
echo “Listing args with \”\$@\”:”
Logic: for
for i in /*
do
echo “Listing $i:”
ls -l $i
read
done
Example 2: Using the for Loop
#!/bin/bash
# compute the average weekly temperature
for num in 1 2 3 4 5 6 7
do
read -p "Enter temp for day $num: " Temp
let TempTotal=$TempTotal+$Temp
done
let AvgTemp=$TempTotal/7
echo "Average temperature: " $AvgTemp
53
A C-like for loop
An alternative form of the for structure is
for (( EXPR1 ; EXPR2 ; EXPR3 ))
do
statements
done
First, the arithmetic expression EXPR1 is evaluated. EXPR2 is then evaluated
repeatedly until it evaluates to 0. Each time EXPR2 is evaluates to a non-zero
value, statements are executed and EXPR3 is evaluated.
$ cat for2.sh
#!/bin/bash
echo –n “Enter a number: ”; read x
let sum=0
for (( i=1 ; $i<$x ; i=$i+1 )) ; do
While Statements
The while structure is a looping structure. Used to execute a set of commands
while a specified condition is true. The loop terminates as soon as the condition
becomes false. If condition never becomes false, loop will never exit.
while expression
do
statements
done
$ cat while.sh
#!/bin/bash
echo –n “Enter a number: ”; read x
let sum=0; let i=1
while [ $i –le $x ]; do
let “sum = $sum + $i”
Example: Using the while Loop
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10 ]
do
echo The counter is $COUNTER
let COUNTER=$COUNTER+1
done
56
Menu
$ cat menu.sh
#!/bin/bash
clear ; loop=y
while [ “$loop” = y ] ;
do
echo “Menu”; echo “====”
echo “D: print the date”
echo “W: print the users who are currently log on.”
echo “P: print the working directory”
echo “Q: quit.”
echo
read –s choice # silent mode: no echo to terminal
case $choice in
D | d) date ;;
W | w) who ;;
P | p) pwd ;;
Find a Pattern and Edit
$ cat grepedit.sh
#!/bin/bash
# Edit argument files $2 ..., that contain pattern $1
if [ $# -le 1 ]
then
echo “Usage: $0 pattern file …” ; exit 1
else
pattern=$1 # Save original $1
shift # shift the positional parameter to the left by 1
while [ $# -gt 0 ] # New $1 is first filename
do
grep “$pattern” $1 > /dev/null
if [ $? -eq 0 ] ; then # If grep found pattern
vi $1 # then vi the file
fi
Example: Using the while Loop
#!/bin/bash
# copies files from home- into the webserver- directory
# A new directory is created every hour
PICSDIR=/home/carol/pics
WEBDIR=/var/www/carol/webcam
while true; do
DATE=`date +%Y%m%d`
HOUR=`date +%H`
mkdir $WEBDIR/"$DATE"
while [ $HOUR -ne "00" ]; do
DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
mkdir "$DESTDIR"
59
Continue Statements
The continue command causes a jump to the next iteration of the loop, skipping
all the remaining commands in that particular loop cycle.
$ cat continue.sh
#!/bin/bash
LIMIT=19
echo
echo “Printing Numbers 1 through 20 (but not 3 and 11)”
a=0
while [ $a -le “$LIMIT” ]; do
a=$(($a+1))
if [ “$a” -eq 3 ] || [ “$a” -eq 11 ]
then
continue
The continue
while [ condition ]
do
cmd-1
continue
This iteration is
over; do the next
cmd-n
iteration
done
echo "done"
61
Break Statements
The break command terminates the loop (breaks out of it).
$ cat break.sh
#!/bin/bash
LIMIT=19
echo
echo “Printing Numbers 1 through 20, but something happens after 2 … ”
a=0
while [ $a -le “$LIMIT” ]
do
a=$(($a+1))
if [ “$a” -gt 2 ]
then
break
fi
The break
while [ condition ]
do
cmd-1
break
This iteration is over
cmd-n
and there are no more
done iterations
echo "done"
63
Example:
for index in 1 2 3 4 5 6 7 8 9 10
do
if [ $index –le 3 ]; then
echo "continue"
continue
fi
echo $index
if [ $index –ge 8 ]; then
echo "break"
break
fi
done
64
Until Statements
The until structure is very similar to the while structure. The until structure loops
until the condition is true. So basically it is “until this condition is true, do this”.
until [expression]
do
statements
done
$ cat countdown.sh
#!/bin/bash
echo “Enter a number: ”; read x
echo ; echo Count Down
until [ “$x” -le 0 ]; do
echo $x
Example: Using the until Loop
#!/bin/bash
Stop="N"
until [ $Stop = "Y" ]; do
ps -A
read -p "want to stop? (Y/N)" reply
Stop=`echo $reply | tr [:lower:] [:upper:]`
done
echo "done"
66
Manipulating Strings
Bash supports a number of string manipulation operations.
${#string} gives the string length
${string:position} extracts sub-string from $string at $position
${string:position:length} extracts $length characters of sub-string from $string at
$position
Example
$ st=0123456789
$ echo ${#st}
10
$ echo ${st:6}
6789
Parameter Substitution
Manipulating and/or expanding variables
${parameter-default}, if parameter not set, use default.
$ echo ${username-`whoami`}
alice
$ username=bob
$ echo ${username-`whoami`}
bob
${parameter=default}, if parameter not set, set it to default.
$ unset username
$ echo ${username=`whoami`}
$ echo $username
alice
Parameter Substitution
${parameter?msg}, if parameter set, use it, else print msg
$ value=${total?’total is not set’}
total: total is not set
$ total=10
$ value=${total?’total is not set’}
$ echo $value
10
Example
#!/bin/bash
OUTFILE=symlinks.list # save file
directory=${1-`pwd`}
for file in “$( find $directory -type l )”
Functions
Functions make scripts easier to maintain. Basically it breaks up the program
into smaller pieces. A function performs an action defined by you, and it can
return a value if you wish.
#!/bin/bash
hello()
{
echo “You are in function hello()”
}
echo “Calling function hello()…”
hello
echo “You are now out of function hello()”
In the above, we called the hello() function by name by using the line: hello .
When this line is executed, bash searches the script for the line hello(). It finds it
right at the top, and executes its contents.
Functions
A shell function is similar to a shell script
– stores a series of commands for execution later
– shell stores functions in memory
– shell executes a shell function in the same shell that called it
must be defined before they can be referenced
usually placed at the beginning of the script
Syntax:
function-name () {
statements
} 71
Example: function
#!/bin/bash
funky () {
# This is a simple function
echo "This is a funky function."
echo "Now exiting funky function."
}
# declaration must precede call:
funky
72
Functions
$ cat function.sh
#!/bin/bash
function check() {
if [ -e "/home/$1" ]
then
return 0
else
return 1
fi
}
echo “Enter the name of the file: ” ; read x
if check $x
then
echo “$x exists !”
Example: Picking a random card from a deck
#!/bin/bash
# Count how many elements.
Suites=“Clubs Diamonds Hearts Spades”
Denominations=“2 3 4 5 6 7 8 9 10 Jack Queen King Ace”
# Read into array variable.
suite=($Suites)
denomination=($Denominations)
# Count how many elements.
num_suites=${#suite[*]}
num_denominations=${#denomination[*]}
echo -n "${denomination[$((RANDOM%num_denominations))]} of "
Example: Changes all filenames to lowercase
#!/bin/bash
for filename in *
# Traverse all files in directory.
do
# Get the file name without the path.
fname=`basename $filename`
# Change name to lowercase.
n=`echo $fname | tr A-Z a-z`
if [ “$fname” != “$n” ]
# Rename only files not already lowercase.
then
mv $fname $n
fi
done
Example: Compare two files with a script
#!/bin/bash
ARGS=2 # Two args to script expected.
if [ $# -ne “$ARGS” ]; then
echo “Usage: `basename $0` file1 file2” ; exit 1
fi
if [[ ! -r "$1" || ! -r "$2" ]] ; then
echo “Both files must exist and be readable.” ; exit 2
fi
# /dev/null buries the output of the “cmp” command.
cmp $1 $2 &> /dev/null
# Also works with 'diff', i.e., diff $1 $2 &> /dev/null
if [ $? -eq 0 ] # Test exit status of “cmp” command.
then
echo “File \“$1\” is identical to file \“$2\”.”
Function parameters
Need not be declared
Arguments provided via function call are accessible inside
function as $1, $2, $3, …
$# reflects number of parameters
$0 still contains name of script
(not name of function)
77
Example: function with parameter
#! /bin/sh
testfile() {
if [ $# -gt 0 ]; then
if [[ -f $1 && -r $1 ]]; then
echo $1 is a readable file
else
echo $1 is not a readable file
fi
fi
}
testfile .
testfile funtest 78
Example: function with parameters
#! /bin/bash
checkfile() {
for file
do
if [ -f "$file" ]; then
echo "$file is a file"
else
if [ -d "$file" ]; then
echo "$file is a directory"
fi
fi
done
} 79
Local Variables in Functions
Variables defined within functions are global,
i.e. their values are known throughout the entire shell program
keyword “local” inside a function definition makes referenced
variables “local” to that function
80
Example: function
#! /bin/bash
global="pretty good variable"
foo () {
local inside="not so good variable"
echo $global
echo $inside
global="better variable"
}
echo $global
foo 81
Example: function
#! /bin/bash
global="pretty good variable"
foo () {
local inside="not so good variable"
echo $global
echo $inside
global="better variable"
}
echo $global
foo 82
Using Arrays with Loops
In the bash shell, we may use arrays. The simplest way to create one is using one of the
two subscripts:
pet[0]=dog
pet[1]=cat
pet[2]=fish
pet=(dog cat fish)
We may have up to 1024 elements. To extract a value, type ${arrayname[i]}
$ echo ${pet[0]}
dog
To extract all the elements, use an asterisk as:
echo ${arrayname[*]}
Debugging
Bash provides two options which will give useful information for debugging
-x : displays each line of the script with variable substitution and before execution
-v : displays each line of the script as typed before execution
Usage:
#!/bin/bash –v or #!/bin/bash –x or #!/bin/bash –xv
$ cat for3.sh
#!/bin/bash –x
echo –n “Enter a number: ”; read x
let sum=0
for (( i=1 ; $i<$x ; i=$i+1 )) ; do
Debugging
$ for3.sh
+ echo –n ‘Enter a number: ’
Enter a number: + read x
3
+ let sum=0
+ (( i=0 ))
+ (( 0<=3 ))
+ let ‘sum = 0 + 0’
+ (( i=0+1 ))
+ (( 1<=3 ))
+ let ‘sum = 0 + 1’
+ (( i=1+1 ))
+ (( 2<=3 ))
+ let ‘sum = 1 + 2’
+ (( i=2+1 ))
+ (( 3<=3 ))
Example: Suite drawing statistics
$ cat cardstats.sh
#!/bin/sh # -xv
N=100000
hits=(0 0 0 0) # initialize hit counters
if [ $# -gt 0 ]; then # check whether there is an argument
N=$1
else # ask for the number if no argument
echo "Enter the number of trials: "
TMOUT=5 # 5 seconds to give the input
read N
fi
i=$N
echo "Generating $N random numbers... please wait."
SECONDS=0 # here is where we really start
while [ $i -gt 0 ]; do # run until the counter gets to zero
case $((RANDOM%4)) in # randmize from 0 to 3
0) let "hits[0]+=1";; # count the hits
1) let "hits[1]=${hits[1]}+1";;
2) let hits[2]=$((${hits[2]}+1));;
Challenge/Project: collect
Write a utility to collect “well-known” files into convenient directory holders.
collect <directory>*
The utility should collect all executables, libraries, sources and includes from each
directory given on the command line or entered by the user (if no arguments were passed)
into separate directories. By default, the allocation is as follows:
– executables go to ~/bin
– libraries (lib*.*) go to ~/lib
– sources (*.c, *.cc, *.cpp, *.cxx) go to ~/src
– includes (*.h, *.hxx) go to ~/inc
The utility should ask whether another directory should be used in place of these default
directories.
Each move should be recorded in a log file that may be used to reverse the moves (extra
points for writing a reverse utility!). The user should have an option to use a log file other
than the default (~/organize.log).
At the end, the utility should print statistics on file allocation: how many directories were