| |||||||||||
| |||||||||||
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 Web Application Deployment - Linux Utilities Web Application Deployment - Linux -An Introduction For Users 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, 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. |
| ||||||||||
PH: 01144 1225 708225 • FAX: 01144 1225 707126 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho | |||||||||||