5 - CSC350 - Shell Scripting Using BASH
5 - CSC350 - Shell Scripting Using BASH
1
Outline
• Introduction
• Variables
• Command Shortcuts
• Tilde Substitution
• Redirection
• Command Substitution
• Arithmetic
• Conditional Expressions
• Control Structures
• F
Functions
i
• Menus: select
2
Introduction
3
Motivation
• Bash is
Bash is
– the default shell for Linux users.
– an attempt to create a
an attempt to create a "best
best of all shells
of all shells"
• provides the most useful features of both the C shell and
Korn shell.
o s e
– compatible with the original UNIX Bourne shell
– an open software
an open software product,
product,
– freely available and can be found in all Linux distributions,
• can
can be downloaded and installed on just about any version
be downloaded and installed on just about any version
of UNIX if it isn't already present.
4
Shell Commands
• alias • kill
• bg • local
• builtin • popd
• case..in..esac
i • pushdhd
• cd • read
• declare • readonly
• dirs • return
• env • select..do..done
• export • set
• fg • source
• for..do..done • trap
• function • unalias
• history • unset
• if..then..elif..then..else..fi • until..do..done
• jobs • while do done
while..do..done
5
Introduction
• On
On Linux systems, Bash is installed as /bin/bash, but
Linux systems Bash is installed as /bin/bash but
/bin/sh is a pointer to /bin/bash,
• The following features of Bash that are new or a bit
The following features of Bash that are new or a bit
different from what has been discussed in previous
chapters include:
chapters include:
– variable manipulation
– arithmetic, conditional expressions, control structures
ih i di i l i l
– shell functions
6
Startup
• Bash is a program.
Bash is a program.
• When a new Bash shell starts,
– it executes commands in the file ".bashrc" in the home directory of
y
the user running Bash.
– The one exception is when Bash is started as a login shell, in which
case it runs the commands in the file " bash profile" in the user's
case it runs the commands in the file ".bash_profile" in the user's
home directory instead.
– So if you want your ".bashrc" file to be executed in your login shell as
well, you have to add this to your ".bash_profile" file:
if [ -f ~/.bashrc ]; then
.~/.bashrc
/ b h
fi
7
Startup
• We'll
We ll see how and why that works later in the
see how and why that works later in the
chapter.
• This is often found by default in ".bash_profile" files
This is often found by default in " bash profile" files
on a system.
• In addition to these two files,
dd h fl
– the system administrator can put initialization commands
appropriate for all users in the file "/etc/profile"
i f ll i h fil "/ / fil "
which Bash will also read and execute.
8
Variables
9
Variables
• Bash allows creation and use of shell variables for
Bash allows creation and use of shell variables for
the following purposes:
1.
1 Value assignment
Value assignment and access
and access
2. Defining and using lists of values [array]
3
3. Testing a value or for existence of a variable
a value or for existence of a variable
4. Reading or writing a variable's value
10
Creating/Assigning a Simple
Variable
• To assign a value to a simple variable, the syntax is similar to
g p , y
that of other shells.
• Example of assigning a simple variable.
{name=value}+
– If a variable doesn't exist, it is implicitly created;
– otherwise, its previous value is overwritten.
– A newly created variable is always local,
• although we may turn it into an environment variable.
• To assign a value that contains spaces, surround the value by
quotes.
• Here are some examples:
$ teamname="Denver
teamname= Denver Broncos"
Broncos
$ gameswon=12
$ gameslost=3
11
Accessing Simple Variables
Syntax
y Action
$name Replaced by the value of name.
${name} Replaced
p byy the value of name. This form is useful if the expression
p is
immediately followed by an alphanumeric that would otherwise be
interpreted as part of the variable name.
${name-word}
${ } Replaced by the value of name if set, and word otherwise.
${name+word} Replaced by word if name is set, and nothing otherwise.
${name=word} Assigns word to the variable name if name is not already set,
set and then
is replaced by the value of name.
${name?word} Replaced by name if name is set. If name is not set, word is displayed
to the
h standard
d d error channel
h l andd the
h shell
h ll is
i exited.
i d If wordd is
i
omitted, then a standard error message is displayed instead.
${#name} Replaced by the length of the value of name.
${#name[*] } Replaced by the number of elements in the array name. 12
Accessing Simple Variables
Syntax
y Action
15
• In the next example,
– I tried to access an undefined variable called grandTotal and received an error
message instead:
i t d
$ total=10 ...assign a variable.
$ value=${total?'total not set'} ...accessed OK.
$ echo $value ...look at its value.
10
$ value=${grandTotal?'grand total not set'} ...not
set.
grandTotal: grand total not set
$ _
• In this example,
– I ran a script that used the same access method as the previous example.
Note that the script terminated when the access error occurred:
$ cat script.sh ...look at the script.
value=${grandTotal?'grand total is not set'}
echo done # this line is never executed.
$ ./script.sh ...run the script.
script.sh: grandTotal: grand total is not set
$ _
16
• In this final example,
– I'll modify some variable values:
$ echo $PWD ...display the current working directory.
/home/glass/dir1
$ echo $HOME
/home/glass
$ echo $
${PWD#$HOME/}...remove
#$ / leading $HOME/
$ /
dir1
$ fileName=menu.sh ...set a variable.
$ echo ${fileName%.sh}.bak ...remove trailing ".sh"
menu.bak ...and add ".bak".
$ x=/one/two/three
$ echo ${x##*}
$_
$ echo ${x##*/}
three
$ echo ${x#*/}
one/two/three 17
Creating/Assigning a List Variable
• declare create
declare create a list of variables, or arrays
a list of variables or arrays
– although simply using a variable in the form of an array
will also work.
will also work.
• Shell command: declare [-axir] [listname]
– If the named variable does not already exist, it is created.
If the named variable does not already exist it is created
– If an array name is not specified when -a is used,
• declare will display
will display all currently defined arrays and their
all currently defined arrays and their
values.
– If
If the
the -x
x option is used, the variable is exported
option is used, the variable is exported to
to
subshells.
– If the –i option is used, the variable is considered integer
p , g
– If the –r option is used, makes the variable read only 18
Creating/Assigning a List Variable
• Here
Here is an example of how you might create a list of
is an example of how you might create a list of
teams:
$ declare -a teamnames
$ teamnames[0]="Dallas Cowboys"
$ teamnames[1]="Washington Redskins"
$ teamnames[2]="New York Giants"
• IIn reality, if you omit the declare
lit if it th d l command, the
d th
other lines will still work as expected.
19
Accessing List Variables
• When accessing array values,
When accessing array values
– you can always put braces around the variable name to
explicitly distinguish it from other text that might be
explicitly distinguish it from other text that might be
around it to prevent the shell from trying to use other text
as part of the variable name.
20
Accessing List Variables
• The
The braces are required when using arrays to
braces are required when using arrays to
distinguish between other shell operators.
– Suppose
Suppose, for example, we have our list of 32 NFL teams
for example we have our list of 32 NFL teams
stored as $teamname[0] .. $teamname[31].
– One might use this information this way:
One might use this information this way:
$ echo "There are ${#teamnames[*]} teams in the NFL"
There are 32 teams in the NFL
$ echo "They are: ${teamnames[*]}"
...
21
Building Lists
• You can build an array or list variable in one of two ways.
y y
1. If you know how many elements you will need,
– you can use the declare built‐in command to define the space
g p
and assign the values into specific locations in the list.
2. If you don't know, or don't care, how many elements will be in the
list,
– you can simply list them and they will be added in the order you
y py y y
specify.
• For example,
– to define our list of NFL teams, of which we know (at least today)
to define our list of NFL teams, of which we know (at least today)
there are 32, you might define it as follows:
$ declare -a teamnames
$ teamnames[0]="Dallas Cowboys"
$ teamnames[1]="Washington Redskins"
$ tea
teamnames[2]="New
a es[ ] e York
o G
Giants"
a ts
... 22
$ teamnames[31]="Houston Texans"
Building Lists
• This can also be done in a single long command:
$ declare -a teamnames
$ teamnames=([0]="Dallas Cowboys" \
[1]="Washington
[ ] g Redskins" \
...
[31]="Houston Texans")
• The backslash is used to tell the shell that the command is continued on the
The backslash is used to tell the shell that the command is continued on the
next line.
• We could have also done it this way:
$ teamnames=("Dallas
teamnames ( Dallas Cowboys" Cowboys "Washington
Washington Redskins"
Redskins \
"New York Giants" "New York Jets" \
...
"Houston Texans")
• If an array tab contains numbers, we declare it in a similar way:
tab=( 5 12 14 3.5)
23
Building Lists
• Note that if you have not assigned values in consecutive
y g
locations
– but skipped around when you ask for the number of values in the array,
– the value will be the actual number of populated elements, not the
th l ill b th t l b f l t d l t t th
largest index defined.
• For example:
p
$ mylist[0]=27
$ mylist[5]=30
$ echo ${#mylist[*]} ...number
n mbe of elements in m mylist[]
list[]
2
$ declare -a ...display defined element values
declare -a mylist='([0]="27" [5]="30")'
$ _
24
Destroying lists
• List
List variables can be deallocated or destroyed using the unset
variables can be deallocated or destroyed using the unset
built‐in to Bash
• Shell command: unset name
unset name[index]
– Deallocates the specified variable or element in the list variable.
• If you have finished using an array, you can deallocate the
space used by the array by destroying it completely.
• It is more likely you will want to remove a specific element in
the array.
$ unset teamnames[17]
– Now our array contains 31 names instead of 32.
Now our array contains 31 names instead of 32
25
Reading a Variable from Standard
Input
• The read command allows you to read variables from standard input
• Shell Command: read { variable }+
– read reads one line from standard input and then assigns successive words
from the line to the specified variables
from the line to the specified variables.
– Any words that are left over are assigned to the last‐named variable.
• If you specify just one variable, the entire line is stored in the variable.
• Here's an example script that prompts a user for his or her full name:
$ cat script.sh ...list the script.
echo -n "Please enter y your name: "
read name # read just one variable.
echo your name is $name # display the variable.
$ bash script.sh...run the script.
Please enter your name: Graham Walker Glass
your name is Graham Walker Glass ...whole line was
read.
$ _
26
• Here's an example that illustrates what happens when you
specify more than one variable:
specify more than one variable:
$ cat
t script.sh
i t h ...list
li t th
the script.
i t
echo -n "Please enter your name: "
read firstName lastName # read two variables.
echo your first name is $firstName
echo your last name is $lastName
$ bash script.sh ...run the script.
Please enter your name: Graham Walker Glass
your first name is Graham ...first word.
your last name is Walker Glass ...the rest.
$ bash script.sh ...run it again.
Please enter your name: Graham
your first name is Graham ...first word.
your last name is
y ...onlyy one.
$ _
27
Exporting Variables
• In all shells, variables are local to the specific shell
In all shells variables are local to the specific shell
– and, unless otherwise specified, are not passed to
subshells.
subshells
• Shell Command: export { variable }+
– export marks the specified variables for export to the
marks the specified variables for export to the
environment.
– If no variables are specified, a list of all the variables
If no variables are specified a list of all the variables
marked for export during the shell session is displayed.
28
Exporting Variables
• Usually, we use uppercase letters to name environment
y, pp
variables.
• The env utility allows you to modify and list environment
variables
variables
• Utility: env { variable=value }* [ command ]
– env assigns values to specified environment variables,
• and then executes an optional command using the new
environment.
– If variables or command are not specified, a list of the current
environment is displayed.
i t i di l d
• In the following example,
– I created a local variable called DATABASE, which I then marked for
export.
– When I created a subshell, a copy of the environment variable was
inherited:
29
$ export ...list my current exports.
export TERM ...set in my ".profile" startup file.
$ DATABASE=/dbase/db ...create a local variable.
$ export DATABASE ...mark it for export.
$ export
p ...note that it's been added.
export DATABASE
export TERM
$ env ...list
list the environment
environment.
DATABASE=/dbase/db
HOME=/home/glass
LOGNAME glass
LOGNAME=glass
PATH=:/bin:/usr/bin
SHELL=/bin/bash
TERM=xterm
USER=glass
$ bash ...create a subshell.
$ echo $DATABASE ...a copy was inherited.
/dbase/db
$ ^D ...terminate subshell.
$ _
30
Exporting Variables
• Bash
Bash provides a shell option that allows you to
provides a shell option that allows you to
specify that, by default, all shell variables be
exported to any subshells created
exported to any subshells created.
• Shell command: set -o allexport
– Tell the shell to export all
T ll h h ll ll variables to subshells.
i bl b h ll
31
Read-Only Variables
• The
The readonly
readonly command allows you to protect variables
command allows you to protect variables
against modification
• Shell Command: readonly y { variable } }*
– readonly makes the specified variables read‐only,
• protecting them against future modification.
– If no variables are specified, a list of the current read‐only variables is
displayed.
– Copies of exported variables do not inherit their read
Copies of exported variables do not inherit their read‐only
only status.
status
• In the following example,
– I protected a local variable from modification.
p
– I then exported the variable and showed that its copy did not inherit
the read‐only status:
32
$ password=Shazam ...assign a local variable.
$ echo $password ...display its value.
Shazam
Sh
$ readonly password ...protect it.
$ readonly ...list all read-only variables.
readonly password
$ password=Phoombah ...try to modify it.
password: is read only
$ export password ...export
export the variable
variable.
$ password=Phoombah ...try to modify it.
password: is read only
$ bash ...create a subshell.
$ readonly ...the exported password is not read-only.
$ echo $password ...its value was copied correctly.
Shazam
$ password=Alacazar ...but its value may be changed.
$ echo $password ...echo its value.
Alacazar
$ ^D ...terminate the subshell.
$ echo $password ...echo original value.
Shazam
$ _
33
Predefined Variables
• Like most shells, Bash defines some variables when it starts
Like most shells, Bash defines some variables when it starts
Name Value
$-
$ The current shell options assigned from the command line or
by the built-in set command discussed later.
$$ The process ID of this shell.
$! The process ID of the last background command.
$# The number of positional parameters.
$? The exit value of the last command.
command
$@ An individually quoted list of all the positional parameters.
$_ The last parameter of the previous command.
$BASH The full pathname of the Bash executable.
$BASH_ENV Location of Bash's startup file (default is ~/.bashrc).
$
$BASH_VERSINFO A read-only array of version information.
$BASH_VERSION Version string. 34
$DIRSTACK Array defining the directory stack (discussed later).
$ENV If this variable is not set, the shell searches the user's home
directory for the ".profile" startup file when a new login shell
is created. If this variable is set, then every new shell
invocation runs the script specified by ENV.
$EUID Read-only value of effective user ID of user running Bash.
$HISTFILE Location of file containing shell history (default ~/.bash_history).
$HISTFILESIZE Maximum number of lines allowed in history file (default is 500).
$SHLVL Level of shell (incremented once each time a Bash process is started,
it shows how deeply the shell is nested)
nested).
$UID Read-only value of user ID of user running Bash. 36
Predefined Variables
• In this example, we illustrate the first three variables.
– the C compiler (gcc) was invoked on a file that didn't exist, and therefore
returned a failure exit code.
$ cat script.sh ...list the script.
echo there are $# command line arguments: $@
gcc $1 # compile the first argument.
echo the last exit value was $? # display
exit code.
$ ./script.sh nofile tmpfile ...execute the
script.
script
there are 2 command line arguments: nofile
tmpfile
gcc: nofile: No such file or directory
gcc: no input files
the last exit value was 1 ...gcc
errored
errored.
$ _ 37
Predefined Variables
• The
The next example illustrates how $!
next example illustrates how $! may be used to kill
may be used to kill
the last background process:
$ sleep 1000 & ...bg process, bash does not report PID.
$ kill $! ...kill it!
29455 Terminated
$ echo $! ...the process ID is still remembered.
29455
$ _
38
Predefined Variables
• Here's a small example that illustrates the predefined variables used to
set the command‐line prompt.
– I set my prompt to something different by assigning a new value to PS1, and I
set PS2 to a new value and illustrated an occasion where the secondary
y
prompt is displayed.
Bash provides a few ways to shorten
p y
commands and arguments you type at the
keyboard.
y
40
Aliases
• Bash
Bash allows you to define your own commands with
allows you to define your own commands with
the alias built‐in command
• Shell Command: alias
Shell Command: alias [word[=string]]
– If you alias a new command word equal to string,
• th
then when you type the command word, the string will be
h t th d d th t i ill b
used in its place (and any succeeding arguments will be
appended to string) and the command will be evaluated.
pp g)
– In the usage "alias word" any alias defined for word will be
printed.
– Its simplest usage "alias" will print all defined aliases.
– there is also a –p argument that can be used
41
Aliases
• Here
Here is an example of defining and using Bash
is an example of defining and using Bash
command aliases:
$ alias dir="ls
dir ls -aF"
aF
$ dir
./ main2.c p.reverse.c reverse.h
../ main2.o palindrome.c reverse.old
$ dir *.c
main2.c
i 2 p.reverse.c palindrome.c
li d
$
42
Aliases
• To
To cause an alias to no longer have a special
cause an alias to no longer have a special
definition, use the unalias built‐in
• Shell Command: unalias
Shell Command: unalias [ [-a]a] {word}+
– Remove the specified alias(es).
– If "‐a" is used, remove all aliases.
If " " i d ll li
• YYou might wish to undefine an alias when you want
i ht i h t d fi li h t
the normal behavior of a command that you
normally alias to a different behavior
ll li t diff tb h i
43
Command History
• Commands you have typed to the shell are stored in a history
y yp y
file defined by the $HISTFILE shell variable.
• By default, the value specifies the file ".bash_history" in the
user's home directory.
' h di
• This file can hold a maximum of $HISTFILESIZE entries, the
default value being 500
default value being 500.
Reading Command History
• To see your shell history, use the built
To see your shell history, use the built‐in
in history command
history command
• Shell Command: history [-c] [n]
– Print out the shell's current command history. If a numeric value n is
specified, show only the last n entries in the history list. If "‐c" is used,
clear the history list.
• Other options of the command history exists…
p y
44
Tilde Substitution
• Any token of the form ~name is subject to tilde substitution.
y j
• The shell checks the password file to see if name is a valid
user name, and if it is, replaces the ~name sequence with the
f ll
full pathname of the user's home directory.
h f h ' h di
• If it isn't, the ~name sequence is left unchanged.
$ pwd
g
/home/glass ...current working
g directory.
y
$ echo ~
/home/glass ...my home directory.
$ cd / ...change to root directory.
$ echo ~+
/ ...current working directory.
$ echo ~-
/home/glass ...previous working directory.
$ echo ~dcox
/home/dcox ...another user's home directory.
$ _
46
Command Substitution
• In
In addition to the older method of command substitution
addition to the older method of command substitution
surrounding the command with grave accents
– Bash allows you to perform command substitution using the syntax
$( command )
• Note that the $ that immediately precedes the open
parentheses is part of the syntax, and is not a prompt.
• Here's an example:
$ echo there are $(who | wc -l) users on the system
there are 6 users on the system
$ _
47
Arithmetic for integers
• To
To perform an arithmetic operation in Bash, you simply put
perform an arithmetic operation in Bash, you simply put
the operation inside a double set of parentheses
(( operation
p )) E.g.: x=$(( 1+3 )) ; echo $x
E.g.: x=$[1+3]; echo $x
$(( expression )) E.g.: if(($x>10)); then …
E.g.: ((x++))
$[ expression
p ] E
E.g.:((x=x+1));
(( 1)) x=$(($x+1));
$(($ 1))
E.g.: x=$((x+1));
E.g.: x=$[$x+1]; x=$[x+1];
49
Conditional Expressions
50
Arithmetic Tests
• Like
Like arithmetic operations, arithmetic tests are enclosed in
arithmetic operations, arithmetic tests are enclosed in
double parentheses.
• The types of comparisons you can do include those
yp p y
<= >= < > Less than or equal to, greater than or equal to, less than, greater than
comparisons.
== != Equal, not equal.
! Logical NOT.
&& Logical AND.
|| Logical OR.
54
File-Oriented Expressions
p
-a file True if the file exists.
-d file True if the file exists and is a directory.
y
-e file True if the file exists.
-f file True if the file exists and is a regular file.
-p file True if the file exists and is a named pipe.
-r file True if the file exists and is readable.
-s
s file T if the
True th file
fil exists
i t andd has
h a size
i greater
t than
th zero.
-w file True if the file is writable.
-x file True if the file exists and is executable.
-L file True if the file exists and is a symbolic link.
file1 nt file2 True if file1 is newer than file2.
file1 ot file2 True if file1 is older than file2.
file1 ef file2 True if file1 and file2 have the same device and inode numbers.
Verify if we have the same file.
file
-O file True if the file exists and is owned by the effective user ID of the
55
user.
File-Oriented Expressions
• [[ ! EXPR ] True if EXPR is false.
! EXPR ] True if EXPR is false
• [ EXPR1 ‐a EXPR2 ] True if both EXPR1 and EXPR2 are
true.
true
• [ EXPR1 ‐o EXPR2 ] True if either EXPR1 or EXPR2 is
true.
• Example
if [ -f test.txt ]; then …
if [ ! -f test.sh ]; then …
if [ -f test.sh -a -f test.txt ]; then …
if [ -f test.sh ] && [ -f test.txt ]; then …
56
File-Oriented Expressions
• A simple example of a file operation might be:
p p p g
$ cat owner.sh
#!/bin/bash
#
if [ -O /etc/passwd ]; then
echo "youy are the owner of / /etc/passwd."
/p
else
echo "you are NOT the owner of
/etc/passwd "
/etc/passwd."
fi
$ bash owner.sh
you are NOT the owner of /etc/passwd.
$_
57
Control Structures
58
if .. then .. elif .. then .. else .. fi
• The if statement lets you compare two or more values and branch to a
block of commands depending on how the values relate
• Shell command: if
if test1; then
commands1;
[elif test2; then
commands2;]
[else commands3;]
fi
• test1 is a conditional expression, which,
p , ,
– if true, causes the commands specified by commands1 to be executed.
– If test1 tests false, then if an "elif" structure is present, the next test, test2, is
evaluated ("else if").
( )
– If test2 evaluates to true, then the commands in commands2 are executed.
– The "else" construct is used when you always want to run commands after a
test evaluated as false.
– We can omit the “;” after the tests when “then” is on a new line.
59
if .. then .. elif .. then .. else .. fi
• As an example, let's assume we have a special case for a couple of our NFL teams
when printing information about them. We might determine which file of
information to print like this:
# $$index has been set to some arbitrary y team in the list
#
if [ "${teamname[$index]}" == "Minnesota Vikings" ]; then
cat "vikings.txt"
vikings.txt # print "special"
special info
elif [ "${teamname[$index]}" == "Chicago Bears" ]; then
cat "bears.txt" # ditto
else
cat "nfl.txt" # for everyone else, print the
standard
fi
60
if .. then .. elif .. then .. else .. fi
File Tests
• File
File test
test expressions test whether a file fits some
expressions test whether a file fits some
particular criteria. The general syntax for a file test is
test option file
• or
[ option file ]
61
if .. then .. elif .. then .. else .. fi
Testing that a file exists
• Consider the following if statement:
$ if [ -d /home/r/bin ] ; then PATH="$PATH:/home/r/bin" ; fi
• Here you are testing whether the directory /home/r/bin exists. If it does,
append it to the variable PATH.
append it to the variable PATH.
• Say you want to execute commands stored in the file $HOME/.bash_aliai if it
exists. You can use the command
$ if [ -f $HOME/
$HOME/.bash_aliai
bash aliai ] ; then $HOME/.bash_aliai
$HOME/ bash aliai ; fi
• An improvement on this would be to test whether the file has any content and,
if so, run the commands stored in it.
• You can change the command to use the ‐
Y h th dt th s option instead of the ‐
ti i t d f th f option to
f ti t
achieve this result:
if [ -s $HOME/.bash_aliai ] ; then $HOME/.bash_aliai ; fi
• Now the commands stored in the file $HOME/.bash_aliai execute if that file
exists and has some content.
62
anny ~> cat msgcheck.sh Checking files
#!/bin/bash
echo "This scripts checks the existence of the
messages file."
echo "Checking..."
if [ -f /var/log/messages ]
then
th
echo "/var/log/messages exists."
fi
echo
echo "...done."
anny ~> ./msgcheck.sh
This scripts checks the existence of the messages file.
Checking...
/var/log/messages exists.
...done.
63
if .. then .. elif .. then .. else .. fi
Testing that a file exists
#!/bin/bash
# This script gives information about a file.
FILENAME="$1“
echo "Properties for $FILENAME:“
if [ -f $FILENAME ]; then
echo "Size
Size is $(ls -l $FILENAME | awk '{ print $5 }')“
}')
else echo "File does not exist.“
fi
64
if .. then .. elif .. then .. else .. fi
Testing exit status
if ! grep $USER /etc/passwd ; then
echo "your user account is not managed
locally";
y
fi
• The same result can be obtained as follows:
The same result can be obtained as follows:
grep $USER /etc/passwd
if [ $? -ne 0 ] ; then
echo "not a local account" ;
fi
65
if .. then .. elif .. then .. else .. fi
Numeric comparisons
#!/bin/bash
num=`wc -l count.sh | awk '{print $1}'`
echo $num
#if [ "$num" -gt "150" ]
if (( $num >= 150 ))
then
echo "you've
you ve worked hard enough for today
today."
else echo "you didn't work hard enough today"
fi
echo "end"
66
if .. then .. elif .. then .. else .. fi
Numeric comparisons
• This
This script is executed by cron every Sunday. If the week
script is executed by cron every Sunday. If the week
number is even, it reminds you to put out the garbage cans:
#!/bin/bash
# Calculate the week number using the date command:
WEEKOFFSET $[ $(d
WEEKOFFSET=$[ $(date
t +"%V") % 2 ]
# Test if we have a remainder. If not, this is an
even week so send a message.
g
# Else, do nothing.
if [ $WEEKOFFSET -eq "0" ]; then
echo "Sunday evening, put out the garbage cans.“
else echo "It is not the time“
fi
67
if .. then .. elif .. then .. else .. fi
String comparisons
#!/bin/bash
if [ "$(whoami)" != 'root' ]; then
echo "You have no permission to run $0 as non-root
user.“
“
exit 1;
fi
• Regular expressions may also be used in
comparisons use double [ ] i e [[ ]]:
comparisons, use double [ ], i.e. [[ ]]:
anny > gender="female"
annyy > if [[ "$gender"
$g == f* ]]
More input> then echo "Pleasure to meet you,
Madame."; fi
Pleasure
l to meet you, Madame.
d
anny > 68
if .. then .. elif .. then .. else .. fi
Checking command line arguments
#!/bin/bash
# This script prints a message about your weight if
you give it your
# weight
i ht i
in kil
kilos and
d h
height
i ht iin centimeters.
ti t
if [ ! $# == 2 ]; then
echo "Usage:
Usage: $0 weight
weight_in_kilos
in kilos length
length_in_cm
in cm“
exit
fi
weight="$1" ; height="$2"
idealweight=$[$height - 110]
if [ $$weight
i ht -le
l $id
$idealweight
l i ht ] ; ththen
echo "You should eat a bit more fat.“
else
echo "You should eat a bit more fruit.“ 69
fi
if .. then .. elif .. then .. else .. fi
Nested if statements
#!/bin/bash
# This script will test if we're in a leap year or not.
year=`date +%Y`
if [ $[$year % 400] -eq "0" ]; then
echo "This is a leap year. February has 29 days.“
elif [ $[$year % 4] -eq 0 ]; then
if [ $[$year % 100] -ne 0 ]; then
echo "This is a leapp yyear, Februaryy has 29 days."
y
else
echo "This is not a leap year. February has 28
d
days."
"
fi
else echo "This
This is not a leap year. February has 28
days.“
70
fi
if .. then .. elif .. then .. else .. fi
Boolean Operations
#!/bin/bash
# This script will test if we're in a leap
year or not.
y
year=`date +%Y`
if (( ("$year"
( $y % 400)
) == "0" )) || ((
("$year" % 4 == "0") && ("$year" % 100 !=
"0") )); then
echo "This is a leap year. Don't forget to
charge the extra day.“
else echo "This is not a leap year. February
has 28 days.“
fi
71
#!/bin/bash
penguin.sh
# This script lets you present different menus to Tux
Tux. He
will only be happy when given a fish. We've also added a
dolphin and (presumably) a camel.
if [ "$menu" == "fish" ]; then
if [ "$animal" == "penguin" ]; then
echo "Hmmmmmm fish... Tux happy!"
elif [ "$animal" == "dolphin" ]; then
echo "Pweetpeettreetppeterdepweet!"
else echo "*prrrrrrrt*"
prrrrrrrt ;
fi
else
if [ "$animal" == "penguin" ]; then
echo "Tux don't like that. Tux wants fish!"; exit 1;
elif [ "$animal" == "dolphin"
p ]; then
echo "Pweepwishpeeterdepweet!" ; exit 2;
else echo "Will you read this sign?!" ; exit 3;
fi
fi 72
#!/bin/bash
# This script acts upon the exit status given by
penguin.sh # export will allows using var in
penguin.sh
export menu="$1“
menu= $1 ; export animal="$2“;
animal= $2 ;
filefeed="./penguin.sh“
$feed $menu $animal
case $? in
1)echo "Guard: You'd better give'm a fish, less they
get violent
violent...";;
";;
2)echo "Guard: It's because of people like you that
they are leaving earth all the time...";;
3)echo "Guard: Buy the food that the Zoo provides
for the animals, you ***, howdo you think we
survive? ;;
survive?";;
*)echo "Guard: Don't forget the guide!";;
esac
73
case .. in .. esac
• The
The case statement lets you specify multiple actions to be
case statement lets you specify multiple actions to be
taken when the value of a variable matches one or more
values
• Shell command: case
case word in
pattern { | pattern }* ) commands ;;
...
esac
– Execute the commands specified by commands when the value of
word matches the pattern specified by pattern.
– The ")" indicates the end of the list of patterns to match.
– The ";;" is required to indicate the end of the commands to be
executed
executed.
74
case .. in .. esac
• For example, a section of Bash shell script to print out the home location
of the NFL teams listed in our earlier example might look like this:
case ${teamname[$index]} in
"Dallas Cowboys") y ) echo "Dallas, , TX" ;;
"Denver Broncos") echo "Denver, CO" ;;
"New York Giants"|"New York Jets") echo "New York,
NY";;
. . .
*) echo "Unknown location" ;;
esac
• Note the special use of the pattern "*" as the last pattern.
• If you go through all the patterns and have never matched anything, this is
useful to catch this situation.
• It is permissible to not match any patterns, in which case, none of the
I i i ibl h i hi h f h
commands will be executed.
75
#!/bin/bash
# This script
p does a very y simple
p test for checking
g
disk space.
space=`df -h | awk '{print $5}' | grep % | grep -v
Use | sort -nn | tail -11 | cut -dd "%" –f
f 1`
1
case $space in
[1-6]*)Message="All
[ ] ) g is q
quiet.";;;;
[7-8]*)Message="Start thinking about cleaning out
some stuff. There's a partition that is $space %
full ";;
full.";;
9[1-8])Message="Better hurry with that new disk...
One partition is $space % full.";;
99)Message="I'm drowning here! There's a partition
at $space %!";;
*)Message="I seem to be running with an nonexistent
amount of disk space...";;
esac
echo $Message
76
#!/bin/bash
echo menu test program
stop=0 # reset loop termination flag.
while test $stop -eq
eq 0 # loop until done.
do
cat << ENDOFMENU # display menu.
1 : print the date.
2, 3: print the current working directory
directory.
4 : exit
ENDOFMENU
echo
echo -nn 'your
your choice? ' # prompt
prompt.
read reply # read response.
echo
case $reply in # process response.
1 )
"1")
date # display date.
;;
"2"|"3")
pwd # display working directory
directory.
;;
"4")
stop=1 # set loop termination flag.
;;
*) # default.
echo illegal choice # error.
;;
esac
echo 77
done
$ bash menu.sh
menu test program
1 : print the date.
2 3
2, 3: print
i t th
the current
t working
ki di
directory.
t
4 : exit
your choice? 1
Thu May 5 07:09:13 CST 2005
1 : print the date.
2, 3: print the current working directory.
4 : exit
your choice? 2
/home/glass
1 : print the date.
2, 3: print the current working directory.
4 : exit
your choice? 5
illegal choice
1 : print the date.
2, 3: print the current working directory.
4 : exit
your choice? 4
78
$ _
for .. do .. done
• The
The for
for construct is best used when you have a known set of
construct is best used when you have a known set of
items you wish to iterate over.
• You might use a comparison to jump out of such a loop, or
g p j p p,
you might simply wish to process each item in the list
sequentially.
• Shell command: for
for name in word { word }*
do
commands
done
Perform commands for each word in list with $name
containing the value of the current word. Another form:
for NAME [in LIST ]; do COMMANDS; done 79
for .. do .. done
• One example of this use might be
p g
– if you needed to sort the contents of all text files in a directory:
$ ls
abc.txt def.txt ghi.txt
$ for file in *.txt
do
sort $file > $file.sorted
done
$ lls
abc.txt def.txt ghi.txt
abc.txt.sorted def.txt.sorted
ghi.txt.sorted
$ _
80
for .. do .. done
Using command substitution for specifying
LIST items
• Using command substitution for specifying LIST
Using command substitution for specifying LIST
items
ls *
*.sh
sh > list
for i in `cat list`; do
cp "$i" "$i"
"$i".bak
bak ; done
• This one lists the files in /sbin that are just plain text
fil
files, and possibly scripts:
d ibl i t
for i in `ls /sbin`; do
file /sbin/$i
/ /$ | grep ASCII; done
81
for .. do .. done
Manipulating a Set of Files
• Say that you need to copy a bunch of files
y y py from one directory
y
to another and change the permissions on the copy.
• You could do this by copying each file and changing the
permissions manually.
i i ll
• A better solution would be to determine the commands you
need to execute in order to copy a file and change its
need to execute in order to copy a file and change its
permissions and then have the computer do this for every file
you were interested in.
• In fact this is one of the most common uses of the for loop –
– iterating over a set of file names and performing some operations
on those files
on those files.
82
for .. do .. done
Manipulating a Set of Files
• The procedure to do this follows:
p
1. Create a for loop with a variable named file or FILE. Other favored
names include i, j, and k. Usually the name of the variable is singular.
p q y p
2. Create a list of files to manipulate. This is frequently accomplished
using the filename substitution
3. Manipulate the files in the body of the loop.
• An
An example of this is the following for loop:
example of this is the following for loop:
for FILE in $HOME/.bash*
do
cp $FILE ${HOME}/public_html
chmod a+r ${HOME}/public_html/${FILE}
#cd ${HOME}/public
${HOME}/public_html html
#chmod a+r .bash*
done
do e
83
for .. do .. done
Manipulating a Set of Files
• In this loop I use filename substitution to obtain a list
of files in my home directory that start with .bash*.
• In the body of the loop,
– I copy each of these files to my public_html directory,
– and then I make them readable by everyone.
– This way people stopping by my Web page can see the
Thi l t i b W b th
scripts.
• Notice
Notice that you are using the name FILE for the
that you are using the name FILE for the
variable.
– This is because each time you are dealing with a single file
f
from a list of files.
li t f fil
– The rationale behind making the for loop's variable
singular, such as FILE instead of FILES, is that you are
g , , y
dealing with only one item from a set of items each time
the loop executes. 84
Loop Control
The break command
• The break command accepts as an argument an integer, greater or equal
to 1, indicating the number of levels to break out of.
d h b fl l b k f
• This feature is useful when nested loops are being used. Consider the
following nested for loops:
for i i
f in 1 2 3 4 5
do
mkdir -p /mnt/backup/docs/ch0${i}
if [ $? -eq 0 ] ; th
then
for j in doc c h m pl sh
do
cp $HOME/docs/ch0${i}/*.${j}
$HOME/docs/ch0${i}/* ${j} /mnt/backup/docs/ch0${i}
if [ $? -ne 0 ] ; then break 2 ; fi
done
else
echo "Could not make backup directory."
fi
done
85
Loop Control
The break command
• In
In this loop, I
this loop, I'm
m making a backup of several
making a backup of several
important files from my home directory to the
backup directory.
p y
• The outer loop takes care of creating the backup
directory, whereas the inner loop copies the
y p p
important files based on the extension.
p y
• In the inner loop, you have a break command with
the argument 2.
– This indicates that if an error occurs while copying you
should break out of both loops, and not just the inner
loop.
86
Loop Control
The continue command
• The continue command is similar to the break command, except that it
causes the current iteration of the loop to exit, rather than the entire
h f h l h h h
loop.
• This command is useful when an error has occurred but you want to try to
execute the next iteration of the loop
execute the next iteration of the loop.
• As an example, the following loop doesn't exit if one of the input files is
bad:
for FILE in $FILES ;
do
if [ ! -f "$FILE" ] ; then
echo "ERROR: $FILE is not a file
file."
"
continue
fi
# process the file
done
• If one of the filenames in $FILES is not a file, this loop skips it, rather than
exiting
exiting.
87
while/until .. do .. done
• Shell commands: while/until
/
while test
do
commands
done
u t
until test
do
commands
done
• In a while statement, perform commands as long as the
expression test evaluates to true.
• In an until
I il statement, perform commands as long as the
f d l h
expression test evaluates to false (i.e., until test is true).
88
while/until .. do .. done
• These constructs are useful when you don't know exactly when the status
of the test condition will be changed.
• Here's an example of a script that uses an until control structure:
$ cat until
until.sh sh ...list
list the script
script.
x=1
until [ $x -gt 3 ]
do
echo x = $x
(( x = $x + 1 )) # x=$[$x+1]
done
$ bash until.sh ...execute the script.
x = 1
x = 2
x = 3
$ _
89
• Here's an example of a script that uses a while control structure to
generate a small multiplication table:
$ cat multi.sh ...list the script.
if [ $# -lt 1 ]; then
echo "Usage:g multi number"
exit
fi
x=1 # set outer loop value
while [ $x -le $1 ] # outer loop
do
y=1 # set inner loop value
while
hil [ $ $y -lel $1 ]
do # generate one table entry
(( entry = $x * $y ))
echo
h -e -n "$entry\t"
"$ t \t"
(( y = $y + 1 )) # update inner loop count
done
echo # blank line
(( x = $x + 1 )) # update outer loop count
done
91
Nesting while Loops
x=0
#while [ $x -lt 10 ]
while ((x < 10 ))
do
y=$x
# while [ $y -ge 0 ]
while (( y >= 0 ))
do
Output
echo -n "$y " 0
((y=y 1))
((y=y-1)) 10
done 210
echo 3210
((
((x=x+1))
1)) 43210
done 543210
6543210
76543210
876543210 92
9876543210
Example
#!/bin/bash
# This generates a file every 5
minutes
while true; do
touch pic-`date +%s`.txt
p 300
sleep
done
93
#!/bin/bash
# This script provides
wisdom
FORTUNE=/usr/games/fortune
while true; do
echo "On which topic do
you want advice?"
advice?
cat << topics echo
politics
startrek
echo -n
n "Make
Make your choice: "
kernelnewbies read topic
sports echo
bofh-excuses
echo "Free advice on the
magic
topic of $topic: "
love
literature echo
drugs $FORTUNE $topic
education echo
topics done 94
#!/bin/bash
# Calculate the average of a series of numbers.
SCORE="0" ; AVERAGE="0"
SUM="0" ; NUM="0"
while
hil ttrue; d
do
echo -n "Enter your score [0-100%] ('q' for quit): "
read SCORE;
if (("$SCORE" < "0")) || (("$SCORE" > "100")); then
echo "Be serious. Common, try again: "
elif [ "$SCORE"
$SCORE == "q"
q ]; then
echo "Average rating: $AVERAGE%."
break
else
SUM=$[$SUM + $SCORE]
NUM=$[$NUM
U $[$ U + 1]]
AVERAGE=$[$SUM / $NUM]
fi
done
echo "Exiting." 95
Validating User Input
• Say that you need to write a script that needs to ask the user
y y p
for the name of a directory. You can use the
• following steps to get information from the users:
1. Ask
1 Ask the user a question.
the user a question
2. Read the user's response.
3. Check to see whether the user responded with the name of a
directory.
directory
• What should you do when the user gives you a response that
is not a directory?
• The simplest choice would be to do nothing, but this is not
very user friendly.
• Your script can be much more user friendly
Your script can be much more user friendly by informing the
by informing the
user of the error and asking for the name of a directory again.
96
Validating User Input
• The
The while
while loop is perfect for doing this.
loop is perfect for doing this.
• In fact, one of the most common uses for the while loop is to
check whether user input has been gathered correctly.
p g y
• Usually a strategy similar to the following is employed:
1. Set a variable's value to null.
2. Start a while loop that exits when the variable's value is not null.
3. In the while loop, ask the user a question and read in the users
response.
response
4. Validate the response.
5. If the response is invalid
p the variable's value is set to null. This enables
the while loop to repeat.
6. If the response is valid, the variable's value is not changed. It continues
to hold the user's response Because the variable's value is not null
to hold the user's response. Because the variable's value is not null,
the while loop exits. 97
Validating User Input
• In the following example, use the commands
– echo to display a string
– read to read in the user's response
• A while loop follows that solves your problem:
A while loop follows that solves your problem:
RESPONSE=
while [ -z "$RESPONSE" ] ; # true if length of var is 0
do
echo "Enter the name of a directory where your files
are located:"
read RESPONSE
if [ ! -d "$RESPONSE" ] ; then
echo "ERROR: Please enter a directory pathname."
RESPONSE=
fi
done
do e
98
Functions
Bash allows you to define functions that
y
may be invoked as shell commands.
99
Functions definition
• Parameters passed to functions are accessible via the standard positional
parameter mechanism.
h
• Functions must be defined before they are used.
• There are two ways to define a function
• function name
{
list of commands
}
or the keyword function may be omitted:
name ()
{
list of commands.
}
• To invoke a function, supply its name followed by the appropriate
parameters.
• For obvious reasons, the shell does not check the number or type of the
parameters.
100
• Here's an example of a script that defines and uses a function that takes
no parameters:
102
Returning from a Function
• The
The return command returns the flow of control back to the
return command returns the flow of control back to the
caller, and has the following syntax
return [ value ]
– When return is used without an argument, the function call returns
immediately with the exit code of the last command that was
executed in the function;
executed in the function;
– otherwise, it returns with its exit code set to value.
– If a return command is executed from the main script, it's equivalent
p, q
to an exit command.
– The exit code is accessible from the caller via the $? variable.
• Here's an example function that multiplies its arguments and
returns the result:
103
Returning from a Function
$ cat func3.sh ...list the script.
p
f () # two-parameter function.
{
(( returnValue = $1 * $2 ))
return $returnValue
}
# main program.
f 3 4 # call function.
result=$? # save exit code
code.
echo return value from function was $result
$ sh func3.sh ...execute the script.
return value
l f
from f
function
i was 12
$ _
104
Access to Functions
• Functions can be exported to subshells in Bash.
Functions can be exported to subshells in Bash.
• This is accomplished with the export built‐in
• Shell command: export
Shell command: export -f functionname
– The export built‐in command used with the ‐f option
exports a function to a subshell the same way exported
exports a function to a subshell the same way exported
shell variable values are exported to subshells.
• Shell command: local name[=value]
– The local built‐in command defines a variable to be local
only to the current function. A variable name can be listed
or a value can be assigned in the same statement.
105
Recursion: Recursive Factorial,
Using Exit Code
• With careful thought, it's perfectly possible to write recursive functions.
factorial () # one-parameter function
{
if (( $1 <= 1 ))
then
return 1 # return result in exit
code.
else
typeset
yp tmp
p # declare two local variables.
typeset result
(( tmp = $1 - 1 ))
factorial $tmp # call recursively.
(( result = $
$? * $$1 ))
return $result # return result in exit code.
fi
}
# main program.
factorial 5 # call function
echo factorial 5 = $? # display exit code.
106
Recursion: Recursive Factorial,
Using Standard Output
factorial() # one-parameter function
{
if (( $1 <= 1 ))
then
echo 1 # echo result to standard output
output.
else
typeset tmp # declare two local variables.
typeset result
(( tmp = $1 - 1 ))
(( result = `factorial $tmp ` * $1 ))
echo $result # echo result to standard output.
fi
}
#
echo factorial $1 = ` factorial $1 ` # display
result.
lt
107
Sharing Functions
• To
To share the source code of a function between
share the source code of a function between
several scripts, place it in a separate file and then
read it using the "." or source
g built‐in commands at
the start of the scripts that use the function
• Shell Command: source fileName
. fileName
– source (or ".") causes a shell to execute every command in
the script called fileName without invoking a subshell.
– It is perfectly legal for fileName to contain further source
commands.
commands
– If an error occurs during the execution of fileName, control
g
is returned to the original shell.
108
Sharing Functions
• In
In the following example, assume that the source code
the following example assume that the source code
of one of the previous factorial scripts was saved in a
file called "fact
file called fact.sh
sh"::
$ cat script.sh ...list the script.
. fact.sh # read function source code.
echo factorial 5 = 'factorial 5' # call the function.
$ sh script.sh ...execute the script.
factorial 5 = 120
$ _
109
Menus: select
• The select command allows you to create simple menus, and
y p ,
has the syntax
select name [ in {word }+ ]
do
list
done
• The select command displays a numbered list of the words
specified by the in clause to the standard error channel
specified by the in clause to the standard error channel,
displays the prompt stored in the special variable PS3, and
then waits for a line of user input.
• When the user enters a line, it's stored in the predefined
variable REPLY, and then one of three things occurs:
110
Menus: select
1. If
If the user entered one of the listed numbers, name is set to
the user entered one of the listed numbers, name is set to
that number, the commands in list are executed, and then
the user is prompted for another choice.
2. If the user entered a blank line, the selection is displayed
again.
3. If the user entered an illegal choice, name is set to null, the
commands in the list are executed, and then the user is
prompted for another choice.
t df th h i
• The next example is a recoding of the menu‐selection
example from earlier in the chapter
example from earlier in the chapter.
• It replaces the while loop and termination logic with a
simpler select command
simpler select command.
111
$ cat newmenu.sh ...list the script.
echo menu test program
select reply in "date" "pwd" "pwd" "exit"
do
case $
$reply
p y in
"date")
date
;; $ sh newmenu
newmenu.sh
sh ...execute
execute the
"pwd") script.
pwd menu test program
;;
1) date
"exit")
break 2) pwd
;; 3) pwd
*) 4) exit
it
echo illegal choice #? 1
;; Fri May 6 21:49:33 CST 2005
esac #? 5
done illegal choice
#? 4
$ _
112
Exercises
113
Exercise 1: junk new utility
• Write
Write a utility called junk
a utility called junk that satisfies the following
that satisfies the following
specification:
• Utility: junk
Utility: junk [ [-l]l] [ [-p]
p] { fileName }*
– junk is a replacement for the rm utility.
– Rather than removing files, it moves them into the
R h h i fil i h i h
subdirectory ".junk" in your home directory.
– If ".junk" doesn't exist, it is automatically created.
If " junk" doesn't exist it is automatically created
– The ‐l option lists the current contents of the ".junk"
directory and
directory, and
– the ‐p option purges ".junk".
114
Exercise 1 (cont.):
junk new utility
Here's an example of junk
p j at work:
$ ls -lG reader.c ...list existing file.
-rw-r--r-- 1 glass 2580 May 4 19:17 reader.c
$ j
junk reader.c ...junk
j it!
$ ls -lG reader.c ...confirm that it was moved.
reader.c not found
$ junk badguy.c ...junk another file.
$ junk -l ...list contents of "junk" directory.
-rw-r--r-- 1 glass 57 May 4 19:17 badguy.c
-rw-r--r-- 1 glass 2580 May 4 19:17 reader.c
$ junk -p ...purge junk.
$ junk -l ...list junk.
$ _
115
Exercise 2: Process management
• Create
Create a process management utility that allows you
a process management utility that allows you
to kill processes based on their CPU usage.
• This kind of utility would be especially useful to
This kind of utility would be especially useful to
system administrators
Extra question:
• Write a shell script that monitor your system by
testing the cpu usage each 5 seconds, and report to
g p g , p
a logfile the date and name of processes that
exceeds a given percentage that should be precise
g p g p
from the command line. 116
Exercise 3: Move and rename files
• Write
Write a Bash script called mv (which replaces the GNU utility
a Bash script called mv (which replaces the GNU utility
mv) that tries to rename the specified file (using the GNU
utility mv), but if the destination file exists, instead creates an
index number to append to the destination file, a sort of
version number. So if I type:
• $ mv a.txt b.txt
• but b.txt already exists, mv will move the file to b.txt.1. Note
th t if b t t 1 already exists, you must rename the file to
that if b.txt.1 l d it t th fil t
b.txt.2, and so on, until you can successfully rename the file
to a name that does not already exist
to a name that does not already exist.
117
Exercise 4: Tracing
What is the output on the screen of the following code?
x=0
while [ $x -lt 10 ]
do
y=$x
while [ $y -ge
ge 0 ]
do
echo -n "$y "
((y=y-1))
done
echo
((x=x+1))
done
118
Exercise 5: Files Backup
• We want to backup all files in the directory /home/tony/OS
We want to backup all files in the directory /home/tony/OS
with the extension .ppt, .doc and .xls. For that, do the
following:
1. Firstly, test if the file update.txt exists in the home directory
and contains the date of the current day. If the condition is
true proceed in the second step, else print out a goodbye
message and exit. Note that the test option –z string is true if
string has zero length.
has zero length
2. Secondly, compress all the files with the extension .ppt, .doc
and .xls and then move the compressed files to the
and .xls, and then move the compressed files to the
directory ~/backup. You need to test if the backup directory
exists, if not you have to create it.
119
Exercise 6: Process monitoring
• We want to monitor the running processes that are
gp
consuming more than 90% of the system memory. For that,
1. Write a shell program that output to the screen the process
ID of the first running process that is taking more than 90%
f h fi i h i ki h %
of the system memory. You can use awk programming.
• An example of the ps u
An example of the ps u command gives:
command gives:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ralph 4000 0.0 0.6 5820 3128 pts/0 Ss 11:42 0:00 bash
ralph
ralph 7952 0 0 0 2
7952 0.0 0.2 2768 1028 pts/0 R+ 14:51 0:00 ps u
2768 1028 pts/0 R+ 14:51 0:00 ps u
120
• Exercise 7
– Write
Write a shell program that displays the name of files in a
a shell program that displays the name of files in a
given directory and the line numbers of each file.
– The program should go through all sub directories of the
chosen directory.
h di t
– The program takes as an argument the name of the
y
directory.
• Exercise 8
– Write a shell program that accepts three arguments and displays them
in inverse order
• Exercise 9
– Write a shell program that displays the system date, the list of
connected users and the processes list
connected users, and the processes list
• Exercise 10
Exercise 10
– Write a shell program that calculates the factorial of a number using 121
functions.
• Exercise 11
– Write a shell program that displays the file names of a given directory
p g p y g y
and that have the following characteristics:
• They are “read only” files
• Contain some specific texts (to be entered as argument)
p ( g )
– Input the directory name and the string of characters that are to be
searched.
• Exercise 12
– Write a shell program that allows to verify and to display if a given
user is the owner of a given directory.
i th f i di t
– Input the name of the directory and the user name as arguments
• Exercise 13
– Write a shell program that can verify the existence of a given file in a
given hierarchy of directories The program should display if the file is
given hierarchy of directories. The program should display if the file is
found inside the current directory or sub directory.
– Input the name of the directory and file as arguments
122
• Exercise 14
– Write
Write a script that takes exactly one argument, a directory name.
a script that takes exactly one argument a directory name
– If the number of arguments is more or less than one, print a usage
message.
– If the argument is not a directory, print another message.
– For the given directory, print the five biggest files and the five files
that were most recently modified.
• Exercise 15
– Display a list of all the users on your system who are logged in.
– From the /etc/group directory, display all lines starting with the string
"daemon"
daemon .
• Exercise 16
Exercise 16
– Make a list of files in your home directory that were changed less than
10 hours ago, using grep.
123
• Exercise 17
– What are the current permissions for your home directory?
– What permissions do users in your group have in your home
directory?
y
– What permissions do users not in your group have in your directory?
• Exercise 18
– Move to different directories on the Unix file system and try using the
y y g
file command to see what different types of files are on the system.
– How about the /bin or /dev directories?
– What types of files can you find?
Wh t t f fil fi d?
– Use the df command with the ‐k option to find out how full the "/"
filesystem is. What is their capacity, and their space available?
– Use the find command to search for files named lpsched file in the
/usr directory system.
124