| |||||||||||
Korn Shell - Interactive and Programming basics
What is a Shell Program / Script? A Shell is a program which reads user inputs and controls program output - a command line interpretter. Instructions typed in are split down into component parts (tokenized) and acted on accordingly - typically with the computer's underlting operating system running one or more programs or commands, and returning the output of those programs as described within the instruction. The term "Shell" is typically used in the Unix and Linux world - a DOS command line interpretter is the near equivalent for Windows. Where you have a requirement to rerun the same series of commands on a Unix / Linux system, you can save your commands / instructions into a file and then perform the file as a whole - and that is commonly known as a "Shell Script" or "Shell Program". All mainstream programming languages include conditional constructs (to allow the programmer to specify code which may or may not be performed depending on the result of a test), loops (to allow a specific piece of code to be repeatedly executed a number of times without it having to be repeated in the program), variables (to allow information to be stored within the program from one operation through to following ones) and functions (to allow a piece of code that's required multiple times to be called up by a single easy name whenever it's needed). Shells are no exception - they include conditionals, loops, variables, and functions. Why are there several different shells available? The original shell - knows as the Bourne Shell - is found in a file called "sh". Dating back many years now, to the days of printing terminals and batch computing, it was (and is) very strong on programming facilities compared to facilities that are really needed for good command line interaction. The Bourne shell remains the bedrock of Unix and Linux systems, with the operating system's internal scripts that are run at startup and shutdown time programmed in "sh". In order to provide better interaction, The C Shell was developed and this provided far greater interaction facilities - for example, the ability to rerun a previous command which is something that is exceedingly useful on the command line, but pretty much unwanted in batch files. The C Shell was adopted as the standard for many users, especially on Unix varients such as SunOS / Solaris. In order to make the best of both worlds, the Korn Shell (ksh) was developed. Compatible with the Bourne Shell, but adding to it the intercative capabiities (all be it with a different syntax) of the C shell, it was / is intended to provide the best of both worlds. And there are other shells you'll come across too - ranging from "bash" - the bourne again shell - which is very popular on Linux systems, through tcsh (an open source varient of the C shell) right up the alphabet to zsh. You may also see reference to the pdksh - the public domain Korn shell - which is in practise the flavour used in Linux. Some exceptions to the "just another shell" rule - note that rsh and ssh are remote shell commands / protocols - not really shells in their own rights, but mechanisms through which shells can be accessed via a network. Rsh allows you to run a command on a remote server, and the ssh program allows you to conatct one machine from a nother on a network, and run commands remotely with the traffic between the two hosts being encrypted to stop intermediate snooping. Korn Shell Basics -* Each instruction starts with the name of the command (which may be something that's built in to the shell, or a separate operating system command). -* Instructions are followed, optionally, by a number of parameters which are separated from one another by white space -* Instructions are terminated by a new line character. Example: $ grep -c public Temperatures.java WellHouseInput.java Temperatures.java:2 WellHouseInput.java:6 $ The instruction is a seperate command called "grep" in this case, and it has four parameters. The first is "-c, the second is "public", the third is "Temperatures.java" and the fourth is "WellHouseInput.java". When run on the machine these notes were written on, you'll see that we typed the command against as shell prompt "$" character, and it produced two lines of output. Metacharacters As well as tokenising and passing through commands, shells support a number of metacharacters which effect how they do that parsing and what they do as they run commands. PIPING AND REDIRECTION > redirects the output from a command (on what is known as STDOUT or the regular job output) to a file named thereafter. If the file already exists, the prior contents are cleared out first. >> redirects the output from a command (on what is known as STDOUT or the regular job output) to a file named thereafter. If the file already exists, new contents are added on to the end < redirects the input to a command (know as STDIN or the regular input) from the named file rather than from the keyboard. | diverts the STDOUT of one command in to the STDIN channel of the next one, thus making a production line of commands. $ ls .. > first $ date > second $ ls .. >> second $ cat -n second | more 1 Sat Sep 22 07:11:39 BST 2007 2 ABC 3 abc.html 4 ac_20060330.xyz 5 ac_20060331.xyz 6 ac_20070123.xyz (etc) $ cat -n < first 1 ABC 2 abc.html 3 ac_20060330.xyz 4 ac_20060331.xyz 5 ac_20070123.xyz As well as STDOUT, commands have a second output channel known as STDERR which is used for error messages. The idea of STDERR being separate is that you can direct the regular output to a file for later use, but still see the error messages on the screen. In the Korn shell, you can divert STDERR too using 2>. $ ls sfdsdf ls: sfdsdf: No such file or directory $ ls sdfsdf > demo ls: sdfsdf: No such file or directory $ ls hjsdfhj 2> demo $ cat demo ls: hjsdfhj: No such file or directory $ ls / wobble > head 2> body $ cat head /: bin boot dev etc $ cat body ls: wobble: No such file or directory $ You can also combine STDOUT and STDERR to the same file using 2>&1. Doing two separate diverts to the same file will NOT work, as one output overrides the other. $ ls / wobble > hh 2>&1 $ ls / wobble > ii 2> ii $ diff ii hh 0a1 > ls: wobble: No such file or directory $ Other combined uses ... you'll often pipe, pipe, pipe, pipe, redirect. Example: $ gzip -dc /usr/share/man/man1/ksh.1.gz | groff -T html > ksh.html $ ls -l total 168 -rw-r--r-- 1 trainee users 38 2007-09-22 07:21 body -rw-r--r-- 1 trainee users 39 2007-09-22 07:18 demo -rw-r--r-- 1 trainee users 2643 2007-09-22 07:11 first -rw-r--r-- 1 trainee users 101 2007-09-22 07:21 head -rw-r--r-- 1 trainee users 139 2007-09-22 07:22 hh -rw-r--r-- 1 trainee users 101 2007-09-22 07:24 ii -rw-r--r-- 1 trainee users 136357 2007-09-22 07:36 ksh.html -rw-r--r-- 1 trainee users 2672 2007-09-22 07:11 second WILD CARDS If you write *.txt to match all the file names that end in .txt, it's actually the shell that's doing the work and providing the extra parameters. You can see this in the Korn shell by doing a set -x, then using a wildcard: $ set -x $ ls -l *.* + ls -l ksh.html ksh.txt -rw-r--r-- 1 trainee users 1150 2007-09-22 07:47 ksh.html -rw-r--r-- 1 trainee users 127555 2007-09-22 07:45 ksh.txt $ This means that you can use the following wildcards to match EXISTING FILE NAMES ONLY (different to Windows Wild cards) - MATCH 0 OR MORE CHARACTERS ? - match any one character [xyz] - match one character from the list ~ - shorthand for your home directory ~fred - shorthand for fred's home directory. Note that a range [a-z] is allowed, as is a ! for not - [!aeiou] Other Korn shell "Wild cards" are: @(...|...) - match one occurrence of any option +(...|...) - match one or more occurrences of any option *(...|...) - match zero or more occurrences of any option ?(...|...) - match zero or one occurrence of any option !(...|...) - match anything that does NOT include any option Examples: + ls body demo first head hh ii ksh.html ksh.txt second $ ls +(ks|he)* + ls head ksh.html ksh.txt head ksh.html ksh.txt $ ls !(hh|ii) + ls body demo first head ksh.html ksh.txt second body demo first head ksh.html ksh.txt second $ Although not REALLY wildcards, don't forget . and .. for "current directory" and "parent directory" respectively. As with all Unix and Linux shells, you must NOT try to use these wild cards to create new file names. QUOTING If you enclose part of your command line in ' characters, you're saying that you wantit taken as a single parameter. Using " characters instead is similar, but allows any shell variable mentioned within to be expanded. And a \ character removes the special significance from just the following character. $ cat peter john glover cat: peter: No such file or directory cat: john: No such file or directory cat: glover: No such file or directory $ cat "peter john glover" cat: peter john glover: No such file or directory $ cat 'peter john glover' cat: peter john glover: No such file or directory $ cat peter\ john glover cat: peter john: No such file or directory cat: glover: No such file or directory $ If you use BACKQUOTES, you're doing the opposite of protecting a part of your command line - you're isntructing the shell to perform the contents before it performs the rest of the command, and substitute the information in place. Thus $ date +%A Saturday $ ls > `date +%A`.txt $ ls -l Sat* -rw-r--r-- 1 trainee users 64 2007-09-22 09:26 Saturday.txt $ CONTINUATION AND SPLITTING A LINE You may specify several commands on one line, separating them with a ; characted, and you may use a \ to continue on form one line to another. $ ls \ > -l total 168 -rw-r--r-- 1 trainee users 38 2007-09-22 07:21 body -rw-r--r-- 1 trainee users 39 2007-09-22 07:18 demo -rw-r--r-- 1 trainee users 2643 2007-09-22 07:11 first -rw-r--r-- 1 trainee users 101 2007-09-22 07:21 head -rw-r--r-- 1 trainee users 139 2007-09-22 07:22 hh -rw-r--r-- 1 trainee users 101 2007-09-22 07:24 ii -rw-r--r-- 1 trainee users 1150 2007-09-22 07:47 ksh.html -rw-r--r-- 1 trainee users 127555 2007-09-22 07:45 ksh.txt -rw-r--r-- 1 trainee users 64 2007-09-22 09:26 Saturday.txt -rw-r--r-- 1 trainee users 2672 2007-09-22 07:11 second $ pwd ; ls /home/trainee/korn body demo first head hh ii ksh.html ksh.txt Saturday.txt second $ ENVIRONMENT VARIABLES When you start a new shell, you're provided with a number of "shell variables" - named memory locations with values relating to the current shell set in them. You may use them within your commands by preceeding them with a $. You may set them using an "=" assignment - NO DOLLAR is this case, please! (You never use a dollar when setting a variable in Shell - only when using it in a readonly context) The default environment variables that you're provided with effect the operation of your shell or commands called up within it in some way or other, and if you change the values they contain you'll effect the subsequent behaviour of the shell and its children. $ echo $WINDOWMANAGER /usr/X11R6/bin/kde $ $ PS1='Hello: ' Hello: pwd /home/trainee/korn Hello: PS1='$ ' $ COMMENTS In the Korn shell, any TOKEN that starts with a # character indicates that the rest of that command is to be treated as a comment. $ echo "The # chacater starts a comment" The # chacater starts a comment $ echo If I type a # in a line If I type a $ # This is a comment $ You are strongly encouraged to comment your scripts, using - Blank lines to separate logical code blocks - Major comments on line starting with # characters - Specific notes about individual commands on the line ends THE HISTORY MECHANISM The Korn shell remembers the commands that you have run, and makes them available to you through the history mechanism. The actual command used is called fc, but it's aliased in several ways to other names. $ history 29 PS1='Hello: ' 30 pwd 31 PS1='$ ' 32 echo The # character starts a comment 33 echo The # character oh - \ 34 echo "The # chacater starts a comment" 35 echo If I type a # in a line 36 # This is a comment 37 alias 38 alias 'll=ls -l' 39 ll 40 ll / 41 FCEDIT=vi 42 export FCEDIT=vi 43 44 alias $ r 35 echo If I type a # in a line If I type a $ Also note that $_ is an environent variable that means "last parameter, previous line". You can also set up a command line editor so that you can interactively use your history list: $ set -o vi $ Then - ESC to enter command mode, KJHL for navigation, i, x, a and more. Storing a shell program in a file You won't always want to re-type your Korn shell instructions each time you want to run then, so you may store them in a file: Here's the file "hello_korn" # Demonstration of a file of Korn Shell commands echo This example has been provided by Well House Consultants echo -n "Copyright - " # Note quotes to add trailing space date ls !(h)* and I can run it as follows: $ ksh hello_korn This example has been provided by Well House Consultants Copyright - Sat Sep 22 10:38:05 BST 2007 hello_korn script_korn $ But I have to KNOW that's a Korn script to run it - if I just want to type its name at the command line, I come across various issues: $ hello_korn ksh: hello_korn: not found $ ./hello_korn ksh: ./hello_korn: cannot execute - Permission denied $ and even when I fix permissions: $ ./hello_korn This example has been provided by Well House Consultants Copyright - Sat Sep 22 10:47:30 BST 2007 ./hello_korn: line 8: syntax error near unexpected token `(' ./hello_korn: line 8: `ls !(h)*' $ Three things: 1. I should change permissions on the file to make it executable: chmod a+x hello_korn or similar 2. I should specifiy at the top of the file that it is to be run under the Korn shell rather than any other, by adding a line #!/usr/bin/ksh 3. I might decide to change my path: export PATH=$PATH:. but bear in mind that there may be security implications of adding any executable files you have in the current directory onto the list of executable syou may run. It then works: $ script_korn This example has been provided by Well House Consultants Copyright - Sat Sep 22 10:50:40 BST 2007 hello_korn script_korn $ THE LIFE OF KORN SHELL A new Korn shell doesn't just start up in isolation; rather, it starts up by reading in some initial settings from /etc/profile and $HOME/.profile if it's a login shell, and then from a file named in $ENV. And if it's a shell which has been called in by another shell, it will inherit environment variables and functions which have been exported by that other shell. Note the /etc/profile will usually contain directives to run additional shell startup scripts such as /etc/ksh.kshrc and $HOME/.kshrc If a shell variable called HISTFILE is set, then the history will be reloaded from that file; if HISTFILE is not set, there's no re-loading of a previous session. Commands available to the Korn Shell user / programmer Like in Tcl, "everything is a command" in Ksh programming. In other words, as you analyse the syntax of the statements of the language you'll always find that, underlying everything else, you have a command name followed by a series of arguments. But there are several groups of commands: SHELL BUILT IN COMMANDS Commands in this group are included within the shell program itself, and may vary somewhat from other commands with the same name in othe Unix or Linux shell programs (you have been warned now, right?) . : [ alias bg break builtin cd command continue echo eval exec exit export false fc fg getopts jobs kill let pwd read readonly return set shift test times trap true typeset ulimit umask unalias unset wait whence COMPOUND STATEMENTS / COMMANDS Rather like the built in commands, these may vary in their Korn shell implementation to their implementation in other shells - although any that you use in the Bourne shell should wok directly here in ksh. ! [[ case do done elif else esac fi for function if in select then time until while { } ALIASED COMMANDS You can make up your own commands too, using the alias command $ alias 'll=ls -l' $ ll total 168 -rw-r--r-- 1 trainee users 38 2007-09-22 07:21 body -rw-r--r-- 1 trainee users 39 2007-09-22 07:18 demo -rw-r--r-- 1 trainee users 2643 2007-09-22 07:11 first -rw-r--r-- 1 trainee users 101 2007-09-22 07:21 head Although useful, you should take care not to rely on too many of your own aliases if you regularly move from one Korn shell environment to another - you need to know the basics. The following aliases are built in to the Korn shell autoload='typeset -fu' functions='typeset -f' hash='alias -t' history='fc -l' integer='typeset -i' local=typeset login='exec login' newgrp='exec newgrp' nohup='nohup ' r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' type='whence -v' unalias will let you delete an alias. SEPARATE PROGRAMS The majority - the vaste majority - of commands you need will be separate programs, and you'll find them on your computer / file system in the various directories listed in $PATH. $ echo $PATH /usr/local/jboss/bin:/usr/local/ant/bin:/opt/SUNWappserver/bin: /opt/SUNWappserver/jdk/bin:/home/trainee/bin:/usr/local/bin:/usr/bin: /usr/X11R6/bin:/bin:/usr/games:/opt/gnome/bin:/opt/kde3/bin: /usr/lib/mit/bin:/usr/lib/mit/sbin:. $ Even commands as fundamental as ls and cp will be found as separate programs. If you need to find out what comes from where, have a look at the whence command $ whence ls /bin/ls $ whence ant /usr/bin/ant $ whence pwd pwd $ whence greet greet $ whence ll 'ls -l' $ or if you prefer $ whence -v pwd pwd is a shell builtin $ whence -v ll ll is an alias for 'ls -l' $ whence -v greet greet is a function $ whence -v whence whence is a shell builtin $ whence -v ln ln is /bin/ln $ FUNCTIONS You can define your own command (script) within your script - nested scripts within the same shell if you like - as a function. A sort of heavy-weight alias, if you like. $ vi funky $ . ./funky Hello World $ greet Hello World $ Let's see the funky file: #!/usr/bin/ksh function greet { echo "Hello World" } greet Some common environment variables and settings The set command allows lots of shell settings (switches) to be thrown. -C noclobber -n noexec (for checking) -v verbose -x xtrace - very useful for learning about how scripts work! vi allows vi style command line editing Environment: CDPATH PATH EDITOR HISTFILE OLDPWD PPID PS1, 2 3 and 4 SECONDS 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 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho |