Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
Korn Shell Scripting - an introduction

Korn Shell Programming

A FIRST PROGRAM AND A FIRST CONDITIONAL

Here's what you might consider to be your first script - it's four lines of code calling up mkdir, cp, ls, wc and sed programs and using a shell builtin echo to perform a backup, into a newly created directory named after the current date.

#!/usr/bin/ksh

# Korn Shell script (1) to back up files

mkdir `date +%F`
cp *.dat `date +%F`
echo -n "Backup copy(ies) made - file count = "
ls `date +%F` | wc -l | sed "s/[ \n]*//g"

How does it work?

$ ./dat_backup
Backup copy(ies) made - file count = 1
$ ./dat_backup
mkdir: cannot create directory `2007-09-22': File exists
Backup copy(ies) made - file count = 1
$

Very well the first time, but then it failed. And that's because mkdir tried to create a directory that already existed!

We can add to that code using a conditional - this first example uses a [ notation which the Korn shell inherits from the Bourne shell - a little ugly, but it works well enough:

#!/usr/bin/ksh

# Korn Shell script (2) to back up files
# Uses bourne shell compatible tests

if [ ! -e `date +%F` ]
then
        mkdir `date +%F`
        echo "Making new directory"
else
        echo "Overwriting directory"
fi
 
cp *.dat `date +%F`
echo -n "Backup copy(ies) made - file count = "
ls `date +%F` | wc -l | sed "s/[ \n]*//g"

And running:

$ ./dat_backup2
Overwriting directory
Backup copy(ies) made - file count = 1
$

Finally, a more flexible and potentially less ugly structure using [[ for the brackets is provided in the Korn shell. This is the one we'll carry on using later in this material.

$ r 145
rm -rf 2007-09-22
$ ./dat_backup3
Making new directory
Backup copy(ies) made - file count = 1
$ ./dat_backup3
Overwriting directory
Backup copy(ies) made - file count = 1
$

Here's the code I used:

#!/usr/bin/ksh

# Korn Shell script (3) to back up files
# Uses bourne shell compatible tests

if [[ ! -e `date +%F` ]]
then
        mkdir `date +%F`
        echo "Making new directory"
else
        echo "Overwriting directory"
fi
 
cp *.dat `date +%F`
echo -n "Backup copy(ies) made - file count = "
ls `date +%F` | wc -l | sed "s/[ \n]*//g"

ARRAYS AND LOOPS

In the Korn shell, all variables are actually arrays - yo do not declate them as such but simple set and get elements using a [ to ] notation. When referencing an element with the shell for reading, you have to help the shell with an extra { to } to delimit the variable name.

#!/usr/bin/ksh

# Setting up and referencing a Ksh array

county=Wiltshire
town[0]=Swindon
town[1]=Salisbury
town[2]=Chippenham
town[3]=Trowbridge
town[4]=Melksham
town[5]='Wootton Bassett'

print "We know about" ${#town[*]} towns in $county

print There is ${town[2]}
print There is ${town[4]}
print There is ${town[5]}

Note also the ${#town[*]} notation to count all members with any key.

$ ./pippa
We know about 6 towns in Wiltshire
There is Chippenham
There is Melksham
There is Wootton Bassett
$

The Korn shell supports while, until and for loops. Let's use examples to loop through our array of towns:

$ ./tracey
We know about 6 towns in Wilthshire
There is Swindon
There is Salisbury
There is Chippenham
There is Trowbridge
There is Melksham
There is Wootton Bassett
$

Here's the program for that:

#!/usr/bin/ksh

county=Wilthshire
town[0]=Swindon
town[1]=Salisbury
town[2]=Chippenham
town[3]=Trowbridge
town[4]=Melksham
town[5]='Wootton Bassett'

print "We know about" ${#town[*]} towns in $county

let a=0
while [[ $a -lt ${#town[*]} ]] ; do
        print There is ${town[$a]}
        let a+=1
done

It's down to which style you choose to use as to whether or not you put the do on the same line as the while, but if you elect to do so you must use that extra ; character.

The let command forces a piece of simple arithmentic (Korn shell maths is integer).

In an instance like this one, where the actual number associated with the town doesn't really matter to us, we may prefer to use a for loop to go through each of the values that's contained in the array, or a part of the array. Note that this for loop structure is quite different to the for loop structure in the C language if you're familiar with that.

$ ./sharon
We know about 6 towns in Wiltshire
There is Swindon
There is Salisbury
There is Chippenham
There is Trowbridge
There is Melksham
There is Wootton
There is Bassett
$

Notice the fact that my script turned "Wootton" and "Bassett" into two different towns!

#!/usr/bin/ksh

# for loop - Korn Shell

county=Wiltshire
town[0]=Swindon
town[1]=Salisbury
town[2]=Chippenham
town[3]=Trowbridge
town[4]=Melksham
town[5]='Wootton Bassett'

print "We know about" ${#town[*]} towns in $county

for place in ${town[*]}; do
        print There is $place
done

OTHER BRANCH CONTROLS

You have already seen if and else. There is also a case available, and you can test implicit conditions within valiables and calculations.

Also available are multiway branch case.

$ ./townline
Where are you wondering about
Orpington
Origin - House, Farm or group of huts
$ ./townline
Where are you wondering about
Chippenham
Saxon Origin
Origin - Village
$

Here's the source:

#!/usr/bin/ksh

# Selects a town ending

print "Where are you wondering about "
read placename

case $placename in
        *ham )
                print "Saxon Origin"
                result="Village";;
        *ton )
                result="House, Farm or group of huts";;
        *bridge )
                result="River Crossing";;
        *bury )
                result="Farm or Village";;
        *minster )
                print "Saxon Origin"
                result="Church";;
        * )
                result"Not in my table!";;
esac

print "Origin - $result"

OTHER LOOPS

You have already seen while and for.

There is also an until loop and a select statement which prompts for user entry and loops on error

$ ./selk
Where to you want to travel?
1) Swindon
2) Chippenham
3) Melksham
4) Trowbridge
5) Westbury
town? 7
invalid. Please try again
town? 3
You have entered Melksham
$

And the script that uses that select:

#!/usr/bin/ksh

PS3='town? '
print "Where to you want to travel?"
select place in Swindon Chippenham Melksham Trowbridge Westbury; do
    if [[ -n $place ]]; then
        print You have entered $place
        break
    else
        print 'invalid. Please try again'
    fi
done

AT THE END OF YOUR CONDITIONAL

You have already see fi and done and esac. Let's look at break, continue and retun.

break says "get me out of this loop .... NOW"

continue says "go back to the top of this loop for the next iteration"

and return says "leave this function .... NOW".

return takes a value as a parameter - the value to be returned

LOGICAL TESTS AND BALANCES

Exit statuses are the only things an if construct can test. But that doesn't mean you can check only whether or not commands ran properly. The shell provides a way of testing a variety of conditions with the [[ ]] construct.

Example of status check:

if cd ${dirname:?"missing directory name."}

Example of using the [ command (yes, really) to test a condition:

if [

And using the [[ construct.

if [[

STRING COMPARISONS

Use the operators = != < > -n and -z (careful - it's a single = sign!); -n for NOT null and -z for zero length.

Code sample:

#!/usr/bin/ksh

# String Test Operators - Ksh

print "Enter your name "
read something

if [[ $something = "Graham" ]] ; then
        echo "Hello Graham"; fi
if [[ $something != "Graham" ]] ; then
        echo "Hello Someone Else"; fi
if [[ $something < "Graham" ]] ; then
        echo "Hello Less Than Graham"; fi
if [[ $something > "Graham" ]] ; then
        echo "Hello Greater Than Graham"; fi
if [[ -n $something ]] ; then
        echo "Hello Someone"; fi
if [[ -z $something ]] ; then
        echo "Hello nobody"; fi

Testing ...

$ ./stroppy
Enter your name
Graham
Hello Graham
Hello Someone
$ ./stroppy
Enter your name
Harry
Hello Someone Else
Hello Greater Than Graham
Hello Someone
$ ./stroppy
Enter your name

Hello Someone Else
Hello Less Than Graham
Hello nobody
$

NUMERIC COMPARISONS

Remember - the Korn shell is an integer shell. Have a look at the bc command if you need to do floating point work.

Numeric comparisons are -eq, -ne, -lt, -le, -ge and -gt. Example:

#!/usr/bin/ksh

# Korn Shell - numeric (integer) testing

print -n "Please enter your age "
read yourage

if [[ $yourage -eq 21 ]] ; then
        print "Congratulations"; fi
if [[ $yourage -ne 21 ]] ; then
        print "Just another year then"; fi
if [[ $yourage -lt 21 ]] ; then
        print "A young one!"; fi
if [[ $yourage -ge 21 ]] ; then
        print "You're 21 on over"; fi
if [[ $yourage -le 21 ]] ; then
        print "You say you're 21 or less"; fi
if [[ $yourage -gt 21 ]] ; then
        print "A mature one"; fi

Testing code:

$ ./numtee
Please enter your age 33
Just another year then
You're 21 on over
A mature one
$ ./numtee
Please enter your age 13
Just another year then
A young one!
You say you're 21 or less
$ ./numtee
Please enter your age 21
Congratulations
You're 21 on over
You say you're 21 or less
$

FILE TESTS

-a file - file exists
-d file - file is a directory
-f file - file is a regular file
-r file - You have read permission on file
-s file - file exists and is not empty
-w file - You have write permission on file
-x file - You have execute permission on file
-O file - You own file
-G file - Your group ID is the same as that of file
file1 -nt file2 - file1 is newer than file2 (based on modification date)
file1 -ot file2 - file1 is older than file2

Let's try those out .. and also start using some command line arguments, which are available in ksh.

$* - all the command line parameters (see $@ if they may be null or have space) $1, $2, $3 etc - command line parameters one by one

#!/usr/bin/ksh

# Comparing one or two files

if [[ -z $1 ]] ; then
        print -u2 "Usage $0 filename [secondfilename]"
        exit
        fi

# If two files are given find which is newer

if [[ -n $2 ]] ; then
        if [[ $1 -nt $2 ]] ; then
                print "$1 is newer"
                use=$1
        else
                print "$2 is newer"
                use=$2
        fi
else
        use=$1
fi
print "About file $use ..."

if [[ ! -a $use ]]; then
    print "file $1 does not exist."
    return 1
fi
if [[ -d $use ]]; then
    print -n "$use is a directory that you may "
    if [[ ! -x $use ]]; then
        print -n "not "
    fi
    print "search."
elif [[ -f $use ]]; then
    print "$use is a regular file."
else
    print "$use is a special type of file."
fi

And some tests of that:

$ ./filestat sharon tracey
tracey is newer
About file tracey ...
tracey is a regular file.
$ ./filestat tracey sharon
tracey is newer
About file tracey ...
tracey is a regular file.
$ ./filestat .. .
. is newer
About file . ...
. is a directory that you may search.
$ ./filestat pippa
About file pippa ...
pippa is a regular file.
$ ./filestat pulla
About file pulla ...
file pulla does not exist.
$



See also Linux Basics Course

Please note that articles in this section of our web site were current and correct to the best of our ability when published, but by the nature of our business may go out of date quite quickly. The quoting of a price, contract term or any other information in this area of our website is NOT an offer to supply now on those terms - please check back via our main web site

Related Material

Web Application Deployment - Korn Shell - interactive and programming facilities
  [1361] - ()
  [1364] - ()
  [1365] - ()
  [1367] - ()
  [1658] - ()
  [1659] - ()
  [1660] - ()

Web Application Deployment - Linux Utilities
  [63] - ()
  [71] - ()
  [1361] - ()
  [1366] - ()
  [1690] - ()
  [2145] - ()
  [2320] - ()
  [2484] - ()
  [2638] - ()
  [3446] - ()
  [3764] - ()
  [3902] - ()
  [4586] - ()
  [4682] - ()

Web Application Deployment - Linux -An Introduction For Users
  [73] - ()
  [74] - ()
  [152] - ()
  [249] - ()
  [430] - ()
  [431] - ()
  [593] - ()
  [659] - ()
  [679] - ()
  [703] - ()
  [710] - ()
  [711] - ()
  [749] - ()
  [984] - ()
  [1012] - ()
  [1013] - ()
  [1068] - ()
  [1259] - ()
  [1287] - ()
  [1288] - ()
  [1366] - ()
  [1408] - ()
  [1438] - ()
  [1527] - ()
  [1651] - ()
  [1764] - ()
  [1803] - ()
  [1893] - ()
  [1897] - ()
  [1902] - ()
  [1904] - ()
  [2201] - ()
  [2203] - ()
  [2299] - ()
  [2300] - ()
  [2479] - ()
  [2494] - ()
  [2636] - ()
  [2831] - ()
  [3179] - ()
  [3256] - ()
  [3791] - ()
  [3819] - ()

resource index - Deployment
Solutions centre home page

You'll find shorter technical items at The Horse's Mouth and delegate's questions answered at the Opentalk forum.

At Well House Consultants, we provide training courses on subjects such as Ruby, Lua, Perl, Python, Linux, C, C++, Tcl/Tk, Tomcat, PHP and MySQL. We're asked (and answer) many questions, and answers to those which are of general interest are published in this area of our site.

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2024: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho

PAGE: http://www.wellho.net/solutions/general- ... ction.html • PAGE BUILT: Wed Mar 28 07:47:11 2012 • BUILD SYSTEM: wizard