home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
317b.lha
/
SKSH_v1.2
/
UserMan.doc.pp
/
UserMan.doc
Wrap
Text File
|
1989-12-06
|
80KB
|
2,509 lines
User's Guide to
SKSH
A ksh-like Shell for the Amiga
Version 1.2
(Copyright) 1989
Steve Koren
November 19, 1989
Table of Contents
Introduction......................................3
Copyright Notice and Other Legal Stuff............4
A Brief History of Unix Shells....................5
SKsh Syntax.......................................6
Credits...........................................8
What SKsh is and is Not...........................9
The Rest of this Document.........................9
SKsh Basics: Executing Commands...................10
SKsh Basics: I/O Redirection......................11
SKsh Basics: Pipe Lines...........................12
SKsh Basics: Strings and Variables................13
SKsh Basics: Parameter Substitution...............15
SKsh Basics: Wildcards............................16
Using SKsh Aliases................................17
Using SKsh Functions..............................18
Function, Alias, Builtin Priority.................20
SKsh Command Substitution.........................21
Control Structures: if-then-elif-else-fi..........23
Control Structures: while-do-done.................24
Control Structures: for-do-done...................25
Test Expressions..................................26
Sub-Shell Execution...............................28
File Name Mapping.................................29
SKsh Scripts......................................30
Command Line Editing and History..................31
Filename Completion...............................34
Index to Users's Guide............................36
SKSH Amiga Shell Page 2 User's Guide
Introduction
SKsh (Amiga-shell) is a shell designed for the Amiga which
closely duplicates functionality of ksh or sh in Unix1. It
is designed for programmers and other expert users who feel
limited by the Amiga's native shell environment. SKsh
provides a very powerful environment; however, it is not for
casual workbench users who want a "point and click" interface.
SKsh provides a large number of features, some of which have
not been previously available in Amiga shells:
* Command substitution (using either backtick or $( )
notations)
* Shell functions with parameters
* Aliases
* Local variables, local functions, and local aliases
* Powerful control structures and tests
* emacs style line editing and history functions
* I/O redirection and pipes
* A large variety of built-in commands
* Unix style wildcards
* Unix filename conventions in AmigaDos (such as ../file
or ~/file)
* Filename completion using <esc><esc> or tab
* Coexistence with scripts from other shells
1_____________________Unix is a trademark of AT&T.
SKSH Amiga Shell Page 3 User's Guide
Copyright Notice and Other Legal Stuff
This software is copyright 1989 Steve Koren. It is not public
domain; however, it is freely distributable, provided that it
is not sold for profit without the written consent of the
author. It may be included in compilations of public domain
software, freely distributable software, and shareware without
written consent of the author provided that no more than $7.00
US 1989 dollars are charged for distribution and disk handling
overhead.
This and all included documents and works are also copyright
1989 Steve Koren, and are included in the terms of the above
paragraph.
Any code included with this software may be freely modified.
However, further distribution of this modified software is
restricted to the condition that a notice of the exact
modifications be clearly included with the documentation. The
existing documentation may not be modified, only appended to.
The sole exception to this rule is that the documentation may
be translated to other languages and the original omitted.
The porting of this software to other computers than the
Commodore Amiga is permitted.
The author of this software does not not officially support
it. It is provided in the hope that it will be useful, but
since it is free, no guarantees of any kind are provided, and
you, the user, accept responsibility for its use.
SKSH Amiga Shell Page 4 User's Guide
A Brief History of Unix Shells
Unix has, for a long time, had two standard shells. csh
provides a programmable shell, and it is favored by some Unix
users because it also provides limited mechanisms for history
and command editing. This editing is cumbersome, however,
using notations like this:
% ^echo^ls -l
to edit lines.
sh provides a more powerful and intuitive programming
environment than csh, so it is preferred for writing scripts.
However, it lacks the editing and history facilities of csh.
ksh is a newer Unix shell, and is fast becoming the dominant
Unix shell. It provides much better editing and history
mechanisms than csh, and a more powerful, but upwardly
compatible programming environment than sh. This, it has the
advantages of both shells.
SKsh on the Amiga is patterned closely after ksh, although ksh
provides a much more powerful environment than does SKsh.
SKSH Amiga Shell Page 5 User's Guide
SKsh Syntax
If you are familiar with ksh or sh programming under Unix
(tm), you will almost immediately become proficient at SKsh.
Although SKsh scripts are not compatible (except in some
specific cases) with those of sh or ksh, the syntax is nearly
identical, and many of the same commands are present. SKsh
operation will be discussed in much greater detail later, but
some examples are presented here, mainly for those who are
already familiar with Unix shells. If you do not understand
these examples, this section can be safely ignored.
A simple command is a single external function, alias,
builtin command, or shell function. For example, "echo
foo" is a simple command, as is "a = 42" or "preferences".
A control structure is a method of directing execution.
Control structures can contain simple commands, other
control structures, pipe-lines, or sub-shells.
if [ $a -gt 0 ]
then
while [ $a -lt 10 ]
do
echo "A = $a"
inc a
done
fi
A pipeline is a sequence of simple commands, control
structures or sub-shells separated by pipe symbols. A pipe
symbol is a vertical bar ('|'). For example, the following
is a pipeline:
for param in "these" are 'parameters' $boo
do
echo $param
done | wc
(notice the pipe symbol in between the for-loop and the
word count command). The input or output from a pipe can
also be re-directed to or from a file.
A subshell is a method of grouping commands, control
structures, pipes, or other sub-shells. Sub-shells are
delimited by either parentheses:
(echo foo; echo bar)
or curly-braces:
{ which emacs; whence emacs }
Sub-shells have certain specific uses, and the two forms
SKSH Amiga Shell Page 6 User's Guide
above differ in their behaviour; this will be explained in
greater detail later.
Command substitution is a method for including the output
of a command as if it was typed into the command line.
Again, this will be explained in greater detail later, but
here are some examples using both the backtick (`) and the
$( ) syntax:
a=`basename foo:bar/not/file`
or
echo $(expr length $(date -y))
A shell function is similar to a script, but it is stored
in the shell itself instead of a file. Thus, it can be
accessed much faster than a script. Here is a sample
function definition:
function param_count {
echo "$# parameters were passed to this function,"
echo "the second of which is $2"
}
Functions can contain local variables, local aliases, and
even local functions, as well as any combination of
commands and control structures. Functions can call other
functions and scripts, as well.
An alias is simply a way to save typing effort. An alias
can be used to take the place of a command and some of its
parameters so that the command is easier to type. For
example,
alias hist = 'history -e'
There are other features as well that will become apparent
later.
SKSH Amiga Shell Page 7 User's Guide
Credits
SKsh was developed on and for the Commodore Amiga.
SKsh was implemented and debugged entirely with Lattice C
5.02. Aside from a few bugs that cause incorrect code to be
generated at times, its a reasonably solid compiler. It has a
great debugger, too.
SKsh was written and copyrighted by Steve Koren.
This manual and the other included documents were written and
are copyrighted by Steve Koren.
This manual was written using excellence! by MSS. It did all
the cool stuff like the table of contents and index.
SKsh is freely distributable.
The SKsh parser was created using Amiga YACC. This yacc was
ported to the Amiga by Bill Lee, and worked great once I
recompiled it with larger tables to handle the SKsh grammar.
I had expected to have problems with a micro based yacc, but I
had none at all.
Until SKsh was usable, I used Matt Dillon's shell version
3.01A during SKsh development. I like that shell far better
than the normal AmigaDos environment. It provides "real"
wildcards, and many other neat things the normal AmigaDos
environment does not.
A bunch of people on Usenet and at the Cleveland Area Amiga
Users's Group have my appreciation for putting up with my
silly questions about invoking programs on the Amiga (which
turns out, unfortunately, not to be a trivial task).
SKsh uses ARP for command execution. There was no other
simple way to do it.
SKSH Amiga Shell Page 8 User's Guide
What SKsh is and is Not
SKsh is a powerful alternative to the normal Amigados shell
environment. This power comes at a price, however. SKsh is
not a tiny program. SKsh is currently about 70 K bytes; small
by Unix standards but quite large for AmigaDos.
SKsh provides a very similar environment to that found under
the two Unix shells mentioned above. It does not claim or
attempt to provide an identical environment. Some simple
scripts will run under SKsh or ksh, but this fact should not
be depended on. In many cases, ksh provides features that
SKsh does not. In some cases, SKsh provides features that ksh
does not. SKsh is, however, not a general purpose programming
language - it is tailored to writing scripts that use other
programs and AmigaDos facilities.
SKsh is not a speed daemon. It would have been possible to
write a much faster programmable shell; however, it would not
have provided the ksh-like environment that SKsh does. The
SKsh script language is adequately fast for simple tasks, but
it is not suitable for complex calculations or algorithms.
SKsh is freely distributable software. It is not public
domain. No one else may sell SKsh without my written
permission, except in the cases detailed in the copyright
notice. You are, however, encouraged to distribute SKsh as
widely as possible. It is completely free; however, with my
other free software package (QRT, a ray tracer) some people
sent money anyway. Any money I do receive from SKsh will be
used for repair, maintenance, and upgrade of my 2000, and to
purchase upgrades to Lattice C and other Amiga software.
The Rest of this Document...
The rest of this document is an intermediate level tutorial
for using SKsh. It assumes that you are familiar with the
basic concept and operation of a command interface, such as
the AmigaDos CLI. If you are already a user of sh or ksh
under Unix, you will probably be able to go through this
document very quickly. I do recommend that you read it,
though, to see what SKsh does and does not do, and to see what
differences there are between SKsh and the Unix shells.
The SKsh reference manual explains each command in greater
detail, although more concisely. This document does not even
come close to covering every SKsh command. It is mean to give
you an understanding of the SKsh environment, so that you can
examine the reference manual for information on specific
commands.
SKSH Amiga Shell Page 9 User's Guide
SKsh Basics: Executing Commands
SKsh can, at the most simple level, be used like the AmigaDos
shell. SKsh will display a prompt; exactly what this prompt
says can be changed in a number of ways, but by default the
prompt contains the current working directory, enclosed in
square brackets, followed by a colon, and highlighted, like
this:
[dh0:usr/graphics]: _
After you see this prompt, you may type commands. It does not
matter if these commands are external or internal to SKsh.
Multiple commands on may be placed on a line if separated by a
semicolon (';'). (Note: a semicolon does not always separate
commands. For example, if the semicolon is quoted, it becomes
part of a string). In addition, any text after a '#' is taken
to be a comment.
Previous commands may be recalled and edited for reuse. In
addition, they may be searched for in the history list. This
will be explained in more detail later; for those who are
familiar with the 'emacs' editor from FSF, SKsh duplicates
some of those keybindings.
In SKsh, pressing control followed by 'c' (^c) will generally
abort whatever SKsh is currently doing and return you to the
SKsh prompt. For example, if you type 'sleep 6000', SKsh will
wait for a very long time before returning to the prompt. You
can press ^c to abort this command. However, if an external,
non-SKsh command is executing, that command may or may not
listen to ^c.
SKSH Amiga Shell Page 10 User's Guide
SKsh Basics: I/O Redirection
The input to or output from commands may be redirected. This
is accomplished by using Unix style operators:
< = redirect input
> = redirect output
>> = redirect output, but append
Any type of command or statement may be redirected. For
example, the following are all equally valid:
c:status > outfile
sksh_script < infile >outfile
while read in_line
do
echo "Line was: $in_line"
done < input_file
{ echo; version; echo } >> out_file
Note in the last two cases that SKsh statements as well as
simple commands can use I/O redirection. This is a powerful
feature provided by Unix shells, but not, until now, by Amiga
shells.
SKSH Amiga Shell Page 11 User's Guide
SKsh Basics: Pipe Lines
A pipe line is simply a series of statements separated by a
pipe symbol ('|'). For example,
[dh0:]: echo "This is a pipe-line" | wc
There can be any number of newlines after the pipe-symbol, but
not before it since a newline typically ends a simple
statement. Thus, this is legal:
[dh0:]: cat my_file.txt |
head -20 |
xd
but this is not:
[dh0:]: cat my_file.txt
| head -20
| xd
since the newline after the 'cat...' terminates the command.
Pipes are not limited to simple commands. They may be used
with any SKsh statement:
[dh0:]: for a in a b c d e
> do
> echo "a = $a"
> done | { read aa; read bb }
[dh0:]: echo $aa
a = a
SKsh was written to operate with the AmigaDos pipe: device,
with each branch of the pipe-line executing as a separate
process. However, some limitations in the way AmigaDos
handles processes made a simple thing very complex.
Therefore, the first release of SKsh uses temporary files in
the pipe-line instead of true inter-process pipes using the
pipe: device. Temporary file pipes are not nearly as useful
as interprocess pipes; they are slower, and are limited by the
free space on the device used to hold the files. However, at
the moment, the capability I need to implement interprocess
pipes is simply not there in a useable manner. If the needed
capability ever shows up on the Amiga, SKsh is written to take
advantage of it, and the code change to do this will be only a
few lines. Interprocess pipes using the pipe: device are
still usable in the normal manner using multiple CLI windows;
it is just not as convenient as the SKsh '|' pipe notation.
SKSH Amiga Shell Page 12 User's Guide
SKsh Basics: Strings and Variables
Strings and variables are basic to the operation of SKsh. A
string is simply a sequence of non-special characters,
optionally surrounded by single or double quotes. For
example, this is a string:
howdy
A string which contains white space or special characters must
be quoted. The most common way to quote a string is to use
double quotes:
"this string contains spaces and < special | symbols"
"this string
contains several
newline characters"
Strings can also be surrounded by single quotes. This has a
slightly different meaning; see the section on variables
below.
A string delimited by doubles quotes can contain the double
quote character itself by prefixing it with a backslash:
"this string contains \" a double quote"
Similarly, a single quoted string can contain a single quote
if prefixed by a backslash. There are also several other
backslash escapes possible:
\n - newline character
\t - tab character
\f - form feed character
\\ - backslash character itself
\^ - the caret character
Any control character can be included in a string by prefixing
it with a caret (^). For example, "^[" is escape.
A variable in SKsh is simply a storage place for strings. Any
number of variables can be created. Variables can be assigned
values using the assignment operator:
[dh0:]: my_var="contents of my_var variable"
[dh0:]: my_var2 = "more stuff"
Note that the second line above, with spaces around the
assignment operator, is legal in SKsh, but not in sh or ksh.
The SKsh assignment operator is upward compatible with the
Unix shells.
Variables can be retrieved by prefixing the variable name with
SKSH Amiga Shell Page 13 User's Guide
a '$'. (In the examples below the results of the commands are
indented for clarity).
[dh0:]: echo $my_var
contents of my_var variable
[dh0:]: echo $my_var2
more stuff
("echo" is a command that simply displays its parameters).
Variables can also be expanded inside of double quoted
strings:
[dh0:]: echo "my_var = $my_var"
my_var = contents of my_var variable
However, variables are not expanded inside of single quoted
strings. For example,
[dh0:]: echo '$my_var'
$my_var
would not display the contents of the variable my_var, but
rather would display the actual string $my_var, including the
'$' symbol.
Variables may contain nearly any amount of information. They
typically are used to contain only small strings and numbers,
but if you wished you could store a whole file in a variable
by saying:
[dh0:]: big_var = $(cat my_file.txt)
(the $( ) notation is simply a way to execute a command and
use the output of the command in another command. It will be
discussed in more detail later. The above command is
equivalent to big_var = `cat my_file`, which may be more
familiar to sh users, but the first example above is
recommended).
SKSH Amiga Shell Page 14 User's Guide
SKsh Basics: Parameter Substitution
SKsh normally eliminates white space (blanks, newlines and
tabs) from between parameters to commands. For example,
notice the spacing in the following command and response:
[dh0:]: echo notice the spacing here
notice the spacing here
If you wish to maintain the spacing above, you must put the
text in either a single or double quoted string, which causes
it to be treated as a single parameter:
[dh0:]: echo 'notice this spacing'
notice this spacing
Even if the string echoed comes from a variable, the same
elimination of white space takes place:
[dh0:]: a='some text'
[dh0:]: echo $a
some text
If you wish to preserve the spacing, you must enclose the
variable in double quotes (remember, variables are expanded in
double but not single quotes):
[dh0:]: a='some text'
[dh0:]: echo "$a"
some text
(Note for advanced users: this action is actually controlled
by a variable called the internal field separator, or IFS.)
Internal SKsh commands can have any number of parameters,
(until you run out of memory). External commands are limited
by the AmigaDos command interpreter, which does not accept
commands longer than 256 characters in version 1.3.
SKSH Amiga Shell Page 15 User's Guide
SKsh Basics: Wildcards
SKsh uses Unix style wildcard patterns to match files. The
following characters have special meaning:
* - matches any number of characters, including zero
? - matches exactly one character
[ ] - characters which enclose a character class
! - negate the pattern
Since wildcards are expanded by SKsh, and not by the command
itself as in AmigaDos, they may be used with any command -
even a command such as 'echo' which does not normally deal
with files (try echo *).
Here are some examples using the first two special types
above:
a*f matches 'af', 'abf', 'aazzzewerf', etc.
a?f matches 'abf', 'acf', but not 'af' or 'aaaf'
The square brackets above are used to define a character
class. A character class is simply way to specify an exact
set of characters. Character classes may contain either a
series of enumerated characters, a range of characters, or a
negation of any of the above. For example,
[abcz] matches the character a, b, c, or z.
[a-cv-z] matches either a, b, c, v, w, y, x, or z.
[!a-d] matches any character except a, b, c, or d.
Character classes may be combined with the * and ? wildcards:
[a-c]*.c matches any file starting with a, b, or c and
ending with '.c'
Wildcards are only expended as normal parameters; that is,
outside of quoted strings of any sort. Wildcards also have
certain other uses in SKsh besides matching files (for
example, see the 'match' or 'set' commands).
Wildcards do not have to be used in only the filename
component of a path. For example, all of the following are
valid wildcard patterns:
sys:*/Format
sys:System/Fo*
mydir/*/*.c
*.[hc]
Wildcards are currently case-sensitive.
(See also: File name mapping)
SKSH Amiga Shell Page 16 User's Guide
Using SKsh Aliases
An 'alias' in SKsh is simply a way to save typing time. An
alias can stand for any series of characters. For example,
perhaps you enjoy seeing the version number of SKsh. You
enjoy it so much, in fact, that you tire of typing 'version'
over and over. You can define an alias, called 'v', that
simply stands for the 'version' command:
[dh0:]: alias v=version
[dh0:]: v
SKsh Version 1.0, Copyright 1989 Steve Koren
You can also include parameters after the alias call. For
example:
[dh0:]: v -d
19:13:18 Oct 12 1989
The alias command only looks at one parameter after the '='
sign, so to include parameters in the alias, you must enclose
the alias definition in quotes:
[dh0:]: alias v='version -d'
[dh0:]: v
19:13:18 Oct 12 1989
To obtain a list of aliases, simply use the alias command by
itself:
[dh0:]: alias
(big list of aliases)
I left out the list of aliases above, because there are a
large number supplied by SKsh itself. One of these built in
aliases is the unalias command. To find out what the
definition of unalias is:
[dh0:]: alias unalias
unalias = unset -a
So, the unalias command simply runs the command 'unset -a'.
Unalias is provided as a built in alias, however, since it is
easier to remember than unset -a. Unalias removes any number
of alias definitions:
[dh0:]: unalias v foo bar
The above line would remove the alias definitions of v, foo,
and bar.
Note that alias commands may be used just like any other
command, in scripts, functions, or substitution statements.
SKSH Amiga Shell Page 17 User's Guide
Using SKsh Functions
While aliases are limited to simple text substitution uses,
functions are vastly more powerful. Functions provide a way
to store SKsh programs within SKsh itself instead of in a
file. Here is an example function that SKsh loads when it
starts up. Don't worry if you don't understand everything in
the function definition; it will be explained later in the
programming sections. For now, just notice that functions can
contain any SKsh statements, and are delimited by curly
braces:
function path { # set or examine path
local comp;
if [ $# -eq 0 ]
then
echo "$PATH"
elif [ "$1" = '-add' -o "$1" = 'add' ]
then
shift
for comp in $* do
if [ $( expr index "$PATH," "$comp," ) -eq 0 ]
then
PATH = "$PATH,$comp"
fi
done
else
PATH="$1"
fi
export PATH
}
That function is one that defines a "path" command in SKsh.
Functions may be used like any other command. You do not even
have to know that they are functions. For example, the above
command, with no parameters, simply prints the path. This can
be output to a file, a follows:
[dh0:]: path > my_file
The path function could also be used in other functions. This
provides a very powerful mechanism for extending SKsh. It
will be particularly interesting for floppy users who do not
want to wait for slow script files.
When SKsh functions are executed, several important things
happen. All variables, functions, and aliases defined inside
the function are local to that function (although this
behaviour is changeable in several ways - see the option
command). Hence:
SKSH Amiga Shell Page 18 User's Guide
function outer {
function inner {
echo "my first parameter is $1"
}
inner $1
}
The function named 'inner' can only be used within the
function named 'outer'. You will notice also that a variable
called $1 is referenced, but not set. There are several
variables that are automatically set by SKsh when a function
(or script) is invoked. The most useful are $0, $1, $2, $3,
etc. They are set to the parameters passed into the function.
Note that $0 is set to the function name itself:
[dh0:]: function test1 {
> echo "0 = $0, 1 = $1, 2 = $2"
> }
[dh0:]: test1 foo bar
0 = test1, 1= foo, 2 = bar
Also note the ">" marks to the left of the 2nd and 3rd lines
of the function. They are the secondary SKsh prompt string,
used when it expects more input. You shouldn't type them.
SKsh also sets the variable '$#' to the number of parameters
passed into the function:
[dh0:]: function countp { echo "Number = $#" }
[dh0:]: countp "this is all one" another param
Number = 3
The variable '$*' is set to the entire parameter list. For
example:
[dh0:]: function pparams { echo "Args = $*" }
[dh0:]: pparams foo bar not
Args = foo bar not
These standard variables can be modified with the 'shift'
command - see the documentation on that command for details.
Any functions or aliases used within a function will operate
correctly even if they are defined after the function itself.
(That is, they are bound dynamically at run-time). This is
different than the ksh behavior.
SKSH Amiga Shell Page 19 User's Guide
Function, Alias, Builtin Priority
In SKsh, you can define a function or alias that overrides the
definition of a an SKsh builtin command (such as the echo
statement). SKsh will evaluate a function definition before
an alias with the same name, and an alias before a builtin
with the same name. Thus, you can redefine the internal sksh
commands.
SKsh still provides a mechanism to access the builtin
commands, even though you might have redefined them. The
force keyword can be used to force the execution of a command
as either a function, an alias, or a builtin. For example,
say you have redefined the sksh date command with a function,
as follows:
[dh0:]: function date {
> echo 'The date command is not available today.'
> }
Any future calls to the date command will have the following
result:
[dh0:]: date
The date command is not available today.
Suppose, however, that you really did wish to access the date
builtin command, and not your function. Use the force keyword
with the -b options (for force execution as a builtin):
[dh0:]: force -b date
Sat Oct 14 11:13:27 1989
This can be particularly useful when you wish to use the
original date command inside of your own. Perhaps you wish to
define a date command which prints "The year is:" followed by
the current year:
[dh0:]: function date {
> echo -n 'The year is: '; force -b date -y
> }
[dh0:]: date
The years is: 1989
In this case, the force -b command must be used to access the
builtin date command. If it was left out, the new date
function would be used instead, calling itself recursively.
SKsh would eventually detect this situation and issue an error
message, but it is not what the command was intended to do.
The force keyword also accepts -f and -a parameters, to force
execution as a function or alias.
SKSH Amiga Shell Page 20 User's Guide
SKsh Command Substitution
SKsh provides several mechanisms for capturing the output of a
statement for subsequent use. The preferred method is to use
the following syntax:
$(command)
SKsh will insert the output of the command as if it was typed
in the SKsh command line. Consider an example. The sksh
function 'basename' prints the file name part of a path name.
For example,
[dh0:]: basename sys:path/to/my/file
file
Now, suppose you wish to obtain the file part of a path string
for use in an sksh function. Normally the 'basename' function
copies the data to the screen. You want to have it in a
variable. If the path you're interested in is in the variable
my_path:
[dh0:]: bn = $(basename $my_path)
The variable 'bn' will contain the desired information.
Parameter substitution may be nested. For example, perhaps
you wish to obtain the length in characters of the file
portion of the path name:
[dh0:]: len = $(expr length $(basename $my_path) )
The alternative syntax for command substitution uses
backticks:
[dh0:]: len = `basename $my_path`
However, the first notation is preferred for a number of
reasons. Using the backtick notation, SKsh reads the entire
substitution command as one token, or set of characters.
Tokens in SKsh are limited by the parser to 1024 characters
(although strings and variables can be of any length). The
parenthetical notation for command substitution has no
restrictions on the length of the command enclosed - it could
be an entire sksh program. Also, the parenthetical notation
is faster than the backtick notation.
You will discover that command substitution is a very useful
thing to have around. One of the more common uses is the
following:
[dh0:]: my_program $(which abc)
Here, my_program is a program which uses abc in some way
(perhaps executes it or edits it). 'abc' is known to be in
SKSH Amiga Shell Page 21 User's Guide
your SKsh path, but my_program does not know about SKsh paths.
The which function in SKsh prints the full path name of a file
in the search path, so the above command saves you from having
to remember and type the full path.
Command substitution works with any SKsh statement. For
example:
[dh0:]: a = $( for a in a b c
> do
> echo "a: $a"
> done )
[dh0:]: echo "$a"
a: a
a: b
a: c
Note that the same variable was used both inside and outside
the command substitution. This is ok, since the statement
list inside the command substitution marks is completely
evaluated before the assignment is made.
Command substitution can also be used with external commands.
Since external binaries do not support command substitution
directly, SKsh stores the results in a temporary file in the
't:' directory. When finished, SKsh deletes the temporary
file. 't:' should be assigned to a fast device, such as a ram
disk. Actually, a subdirectory on the ram disk is best, so
that SKsh's temporary files won't normally be seen.
SKSH Amiga Shell Page 22 User's Guide
Control Structures: if-then-elif-else-fi
SKsh provides a set of control structures for directing
execution. The most common of these is the if-then-elif-else-
fi statement. It has several forms, but the most common are
these:
if [ test expression ]
then
statement
list
fi
The test expression is evaluated (more on test expressions
later), and if it is true, the statement list is executed.
The if statement can have an else part:
if [ expression ]
then
statement list
else
statement list
fi
It can also have any number of else-if expressions:
if [ expression ]
then
stmt_list
elif [ expression ]
stmt_list
else
stmt_list
fi
Any valid SKsh statement list can be used inside the if:
if [ $a -lt 10 ]
then
a = 20
echo "a WAS less than ten, but now it's $a"
fi
An alternative form of the if statement can be used to test
the return code from a command. For example,
if cmp -s file1 file2
then
echo 'Files are the same'
fi
If the command following the if keyword returns TRUE (or a
zero return code), the if statement proceeds as if an
expression returned true.
SKSH Amiga Shell Page 23 User's Guide
Control Structures: while-do-done
A while loop is simply a method for executing a statement list
as long as a certain given condition is true. For example,
while [ ! -d ram:my_dir ]
do
sleep 10
done
which is an endless loop which waits until a given directory
exists (because another process created it). It checks for
the existence of ram:my_dir every 10 seconds. (Again test
expressions will be explained in detail later). As with if-
then-else statements, a while statement can examine the return
code from a command. A particularly useful while loop of that
form is the following:
while read in_line
do
echo "We read: $in_line"
done < input_file
That while loop executes as long as the read command returns
TRUE. The read command returns FALSE upon reaching the end of
the input file, so the loop terminates then. The entire while
loop has its input redirected from a given file. In practice,
of course, the echo statement would be replaced by the code
which accomplishes what you desire. Here is another example,
like the above, but which is combined with SKsh command
substitution:
my_var = $( while read in_line
do
echo "We Read: $in_line"
done < input_file
);
That is identical to the above loop, but saves the output in a
variable called my_var. You could then echo "$my_var" to
retrieve this output.
SKSH Amiga Shell Page 24 User's Guide
Control Structures: for-do-done
SKsh provides a for-do loop, but it differs from the for loops
provided with more most programming languages. In SKsh, for
loops are used to execute a series of statements for each
parameters in a list. For example,
for my_param in abc def ghi
do
echo "my_param = $my_param"
done
The statement list inside the for loop is executed once for
each parameter, and each time, the variable 'my_var' is set to
the parameter in question. That is, the first time through
the loop, my_var is abc, the second time, def, and the third,
ghi. For loops are useful when combined with wildcard
patterns:
for file in *.c
do
cp $file dh0:backups/$file.bak
done
That loop executes once for each c code file in the current
directory, copying the file to the directory dh0:backups and
adding a '.bak' extension in the process. After you gain
experience with SKsh, you will become proficient at executing
similar simple programs from the command line. Even though
this loop is only four lines, it is quite useful. In fact, it
could be shortened to one line by separating the components
with ';'. This loop has been extended to also copy .h files:
for file in *.c *.h; do cp $file dh0:backups/$file.bak; done
For loops can only index parameters. They cannot be used to
count. For that, you must use a while loop with the inc or
expr function.
SKSH Amiga Shell Page 25 User's Guide
Test Expressions
Test expression are used in if statements and while statements
to test a given expression and return TRUE or FALSE
appropriately. Test expressions are enclosed in square
brackets ('[ ]'). The following simple operators are
available:
-f fspec TRUE if fspec exists and is a file
-d fspec TRUE if fspec exists and is a directory
-s fspec TRUE if fspec is a file and has a size of 0
-r fspec TRUE if fspec exists and is readable
-w fspec TRUE if fspec exists and is writable
-x fspec TRUE if fspec exists and is executable
-S fspec TRUE if fspec exists and the script bit is set
-P fspec TRUE if fspec exists and the pure bit is set
-A fspec TRUE if fspec exists and the archive bit is set
-z string TRUE if string has a length of 0
-n string TRUE if string has a non-zero length
The following comparison operators are available:
n1 -eq n2 TRUE if n1 is numerically equal to n2
n1 -ne n2 TRUE if n1 is numerically unequal to n2
n1 -lt n2 TRUE if n1 is numerically less than n2
n1 -gt n2 TRUE if n1 is numerically greater than n2
n1 -le n2 TRUE if n1 is less than or equal to n2
n1 -gt n2 TRUE if n1 is greater than or equal to n2
s1 = s2 TRUE if s1 is the same string as s2
s1 != s2 TRUE if s1 is not the same string as s2
Also, boolean operators are available:
! e1 TRUE if sub-expression e1 is false
e1 -a e2 TRUE if e1 and e2 are both TRUE
e1 -o e2 TRUE if e1 or e2 is TRUE
Thus, the following expressions are all TRUE:
[ 1 -lt 3 ]
[ 3 -lt 2 -o 1 -lt 0 -o 3 -eq 3 ]
[ -z '' ]
[ -n "hi" ]
[ ! -z "hi" ]
[ a = 'a' ]
[ 'xyz' != 'abc' ]
[ -d 'c:' ]
[ -f 'c:dir' -a -f 's:startup-sequence' ]
The boolean and operator has a high precedence than the
boolean -o operator. Note also that test expressions do not
print their result; they simple set the return code, which can
then be tested for. A return code of zero means TRUE. Here
is an example usage of a test expression:
SKSH Amiga Shell Page 26 User's Guide
i = 1
while [ $i -le 10 ]
do
echo "index variable = $i"
inc i
done
Here is another example:
function my_func {
if [ $# -ne 3 ]
then
echo "This function requires exactly 3 parameters"
return
fi
}
The inc command is simply a way to increment a variable.
There are other ways do it, but inc is the fastest.
Test expressions are related to, but should not be confused
with, the expr command.
SKSH Amiga Shell Page 27 User's Guide
Sub-Shell Execution
SKsh provides two mechanisms for grouping commands; they are
closely related both in behaviour and syntax, but differ in an
important way.
If a series of statements is grouped within either curly-
braces '{ }' or parentheses '( )', that statement list is said
to be executed within a sub shell. For example:
{ echo foo; echo bar }
and
( read foo; read bar )
are both sub-shell statements. Subshells group their enclosed
commands, so that all the commands within the subshell share a
common environment. One use for this is to give all the
commands a common input or output. For example:
{ c:status
echo "Done with status command"
c:dir
echo "Done with dir command"
} > out_file
The output of all the commands within the subshell goes to a
common file. This works for input, as well:
{ read foo; read bar } < in_file
If you tried to redirect the input of each read command
separately, both 'foo' and 'bar' would contain the same
information. By using a sub-shell, the reads are sequential
from the input file.
The parenthetical subshell syntax differs from the above form
only in that any variables declared within the subshell are
local. For example,
[dh0:] answer = 42; echo $answer
42
[dh0:]: ( answer = 7; echo $answer )
7
[dh0:]: echo $answer
42
Notice that the answer variable is 42 both before and after
the subshell, but is 7 within it. Because this type of
subshell allocates space for local variables, the first form
is both faster and uses less memory. It is the preferred
form, unless you do in fact need local variables. (Functions
and aliases declared within the parenthetical subshell are
local as well).
SKSH Amiga Shell Page 28 User's Guide
File Name Mapping
When SKsh sees an unquoted file name, it maps the file name
from a Unix style file name to an AmigaDos style file name.
The Unix style has several advantages. First and foremost, a
single dot ('.') can be used to specify the current working
directory. For example,
[dh0:]: assign this_dir: .
[dh0:]: HOME=.
assigns 'this_dir' (a device) to the current working
directory, and then sets the SKsh home directory to the
current directory. The dot can be used in any command, such
as 'cp' or 'mv', but it cannot be quoted or it looses its
magic properties and becomes just a dot. For example,
[dh0:]: echo .
dh0:appl/excellence!/documents/SKSH
[dh0:]: echo "."
.
In addition, a path beginning with a slash ('/') will be
mapped by SKsh to be an AmigaDos absolute path name instead of
a relative path name. For example,
run lse /usr/src/SKsh/Parser.y
really edits the file 'dh0:usr/src/SKsh/Parser.y' if the
current device is dh0:. Also, SKsh maps two sequential dots
('..') to be the parent directory of the current directory
(which in AmigaDos is specified with a slash):
run emacs ../../my_file.c
The file my_file.c in the directory two levels above the
current directory is loaded into emacs.
A tilde ('~') can be used to specify the contents of the HOME
variable. For example, if HOME is 'sys:usr/src/SKsh',
[dh0:]: echo ~/Parser.y
sys:usr/src/SKsh/Parser.y
SKsh can be instructed not to perform this file name mapping.
See the options command for details.
SKSH Amiga Shell Page 29 User's Guide
SKsh Scripts
If a file containing SKsh commands is in the SKsh search path,
and has its script bit set, SKsh will execute the file
directly as if it was a binary file; there is no need to use
an "execute" or other special command. Normally, SKsh
executes the file in its own sub-shell. Thus, variables,
functions, and aliases defined within the script file are
local. SKsh can also "source" files (execute them but not in
a subshell).
SKsh will happily co-exist with scripts from other shells. If
SKsh detects a file with the script bit set, it first examines
the first two characters of the file. If they are '#!' or
';!' SKsh reads the rest of the first line, appends the name
of the script file, and passes the string to AmigaDos to be
executed. For example, on my system I have scripts from SKsh,
Matt Dillon's shell, and the AmigaDos "execute" command. My
scripts either begin with:
#!sys:bin/shell
if the script is to be executed by Matt's shell, or
;!c:execute
if the file is an "execute" script. Since the first character
is recognized by the appropriate shell as a comment, the
script runs fine, and SKsh knows to pass execution to the
correct shell. It is important that there are no leading
blanks or newlines before the '#!' or ';!'; they must be the
first two characters of the file. This mechanism can be used
with any other Amiga shell that recognizes '#' or ';' as a
comment character.
If the script bit is not set, SKsh will ignore the file unless
you explicitly use the 'source' command. Also, if the shell
does not automatically exit after executing the script, you
must include an explicit exit statement at the end of the
script (such as with Matt Dillon's Shell).
(Note: there seems to be a bug someplace with using ;!execute
for AmigaDos execute scripts. It seems that execute sometimes
returns before the script has finished running, and things
tend to get a bit confused. I do not think this is an SKsh
problem, since I run the execute command the same way as I run
anything else).
SKSH Amiga Shell Page 30 User's Guide
Command Line Editing and History
SKsh provides mechanisms for recalling and editing previous
commands. To obtain a list of previous commands, use the
history command. By default, SKsh keeps the previous 32
commands, although this number can be changed by setting the
HISTSIZE variable.
In addition, command line editing is available (but can be
turned off - see the options command). The following keys
have special meaning (the caret mark means hold down the
control key and press the following character):
^p or up arrow - recall previous command
^n or down arrow - recall next command
^b or left arrow - move cursor left
^f or right arrow - move cursor right
^m or return - accept and execute current line
^a or shift-left - move to beginning of line
^e or shift-right - move to end of line
^k - kill to end of line
^l - redraw the current line
^d or delete key - delete current character
^h or backspace - delete previous character
esc-f - move forward one word
esc-b - move backward one word
esc-d - delete the next word
esc-backspace - delete the previous word
esc-< or shift-up - move to first line in history
esc-> or shift-down - move to last line in history
esc-esc or tab - filename completion
esc-= - List matching file names
esc-* - Insert matching file names
esc-. - Insert last param of prev line
^r - reverse search for line
^o - execute line, move to next
^u - multiply next command by 4
function keys - insert defined text
The basic editing commands are self explanatory, but the
others may not be. The reverse search command is used to
search for a string in the history list, and then display the
line containing that string for further editing. For example,
suppose your history list contained 4 lines, as follows:
[dh0]: history
1: echo 'This is a test'
2: version
3: date
4: history
Then, at the SKsh prompt, type a substring from any previous
command:
SKSH Amiga Shell Page 31 User's Guide
[dh0:]: test
When you press ^r, the most recent line containing the
substring will be displayed and available for editing:
[dh0:]: echo 'This is a test'
This line can be edited, or accepted as is by pressing return.
If it is not the correct line, pressing ^r yet again will
start the reverse search again beginning with the line
previous to the one displayed. Thus, multiple ^r's can be
used to access the desired line.
If the line is changed in any way, it will be re-entered at
bottom of the history list as a new command. If it is not
edited, it will simply be executed, but not inserted again
into the history list (although this behaviour can be changed
with the options command.
The ^o key is useful for executing a series of commands
multiple times. Suppose your history list looks like this:
1: echo $HISTSIZE
2: date
3: echo 'command 1'
4: echo 'command 2'
5: echo 'command 3'
Use the ^p key or up arrow to move to the 3rd line. By
pressing the ^o key, that line is executed, and SKsh remembers
which line that was. By pressing ^o again, the next line is
executed. Upon reaching the end of the list, SKsh moves to
the first line upon which ^o was used. In this manner,
'command 1', 'command 2', and 'command 3' would be echoed
repeatedly. Using any other movement or editing command will
cause SKsh to forget which line was the first, and you will
have to move to it again.
The ^u key causes the next command to be repeated four times.
For example, pressing ^u followed by the '-' key inserts four
dashes. Pressing ^u followed by the delete key deletes four
characters. The action of ^u is recursive; two ^u's in a row
will repeat the next command 16 times. Three would repeat 64
times. Therefore, to insert a row of 64 dashes, use
'^u^u^u-'.
If you press a function key, SKsh will examine the contents of
the variable with the same name. For example, pressing f1
would cause SKsh to look for a variable named 'f1', and if
found, insert the text it contains as if you had typed it. If
the text ends in a newline, SKsh will execute the command
immediately; otherwise, it will simply display it for editing
or execution. For example:
SKSH Amiga Shell Page 32 User's Guide
[dh0:]: f1="echo testing"
would would just display "echo testing" when f1 is pressed,
but:
[dh0:]: f1="echo testing\n"
would execute the command as well.
<esc>. will insert the last parameter of the previous line.
For example, suppose you have typed:
[dh0:]: ll some_file_name
Now, you can type:
[dh0:]: rm
and press <esc>., which will insert some_file_name:
[dh0:]: rm some_file_name
In addition to the interactive editing facilities, a single
command can be executed with the 'history -e' command. You
can specify either a substring of the command, its absolute
number, or its relative number by using a negative offset.
For example, given the above history list, all of the
following would echo 'command 2':
[dh0:]: history -e 'd 2'
[dh0:]: history -e 4
[dh0:]: history -e -2
The executed command is not placed at the end of the history
list (see the options command). For convenience, 'history -e'
has been aliased to '!'. Also, 'history -e -1' has been
aliased to '!!' (similar to csh, except that in SKsh there
must be a space between the '!' and the parameter).
If you type a command line that would wrap onto the next line,
SKsh will instead scroll the line 12 characters to the left
and let you continue typing. If you move off either side of
the "sliding window", sksh will adjust the line accordingly.
If this behaviour does not appear to be acting correctly,
check the value of the COLUMNS and PNPC variables, described
in the Reference Manual. The COLUMNS variable should be set
to the number of columns in the current window, and PNPC
should be set to the number of non-printable ANSI control
characters in the SKsh prompt (21 for the default prompt). If
either of these numbers are wrong, long lines will display
improperly. Also, SKsh line editing can be turned off
completely; see the options command for details. In this
case, no line scrolling is performed. If the COLUMNS variable
is set to less than 15, SKsh will get confused.
SKSH Amiga Shell Page 33 User's Guide
Filename Completion
SKsh supports filename completion using <esc><esc> or tab.
For example, suppose your current working directory contains
the following files:
my_file.c
another_c_file.c
this_is_a_long_filename
test_file2
test_file3
picture.ham
picture1.ham
picture2.ham
If SKsh command line editing is turned on (see the options
command), you can insert any file name into the command line
by typing part of the file name and pressing the escape key
twice. For example, suppose you typed:
[dh0:]: cat ano
and pressed <esc><esc>. SKsh would fill in the rest of the
file name for you:
[dh0:]: cat another_c_file.c
In fact, since 'a' is enough to uniquely specify the file
name, you could have typed 'a<esc><esc>' for the same effect.
In the case of 'test_file2' and 'test_file3' above, typing
'te' is not enough to uniquely specify the file, but SKsh will
help here too by filling in as much as it can:
[dh0:]: echo te
(press <esc><esc>)
[dh0:]: echo test_file
You would then have to type either '2' or '3', but you have
still saved 7 characters of typing.
Filename completion is useful not only to save typing, but to
insure that you have not mis-typed the file name. You can use
filename completion on paths, as well:
[dh0:]: sys:S (press <esc><esc>)
[dh0:]: sys:System/Fo (type /Fo and <esc><esc)
[dh0:]: sys:System/Format
The tab key can also be used for filename completion if the
proper option to SKsh is set (see the options command).
SKSH Amiga Shell Page 34 User's Guide
Case is significant in filename completion. Also, if file
name mapping is enabled (see the options command), it will be
performed on the current file name, if applicable. Thus,
'/System/Fo' will be changed to ':System/Format' (notice the
first slash is changed to a colon).
In SKsh 1.1 or later, there are two additional filename
completion features. You can type a partial filename
(optionally using wildcard patterns), press <esc>=, and SKsh
will list all matching files as if an '*' were appended to the
filename you typed. It will the re-display your command line
so you can continue typing:
[dh0:]: show pic ( press <esc>=)
1) picture.ham
2) picture1.ham
3) picture2.ham
[dh0:]: show pic
You can then continue typing, but you can see the matching
files. This is useful when you have typed part of a command,
and then think 'Hmm, what was that file called?'. The
filename you type can contain wilcard patterns, as well.
Also in SKsh 1.1 or later, <esc>* will insert matching file
names in the command line. Again, given the above example,
you could type
[dh0:]: show *.ham
and press <esc>*. SKsh will re-write the command line as
follows:
[dh0:]: show picture.ham picture1.ham picture2.ham
Using <esc>*, the pattern must match the files exactly; SKsh
does not append a '*' for you as it does with <esc>=.
SKsh is, I believe, the first Amiga shell to offer filename
completion. You'll find it addictive. It works best with
hard or ram disks, since the directory seek speed is faster.
SKSH Amiga Shell Page 35 User's Guide
Index to Users's Guide
$# 7, 18-19, 27
$( 3, 7, 14, 18, 21-22, 24
$* 18-19
$0 19
$1 18-19
$2 7, 19
( ) 3, 7, 14, 28
-a 10, 17-18, 20, 26
-d fspec 26
-eq 18, 26
-f fspec 26
-gt 6, 26
-le 26-27
-lt 6, 23, 26
-n string 26
-ne 26-27
-o 18, 26
-r fspec 26
-s fspec 26
-w fspec 26
-x fspec 26
-z string 26
<esc><esc> 3, 34
alias 2-3, 6-7, 17-20, 28, 30, 33
append 4, 11, 30
assignment 13, 22
backspace 31
backticks 21
blanks 15, 30
boolean operators 26
character class 16
COLUMNS 33
Command Substitution 2-3, 7, 21-22, 24
comment 10, 30
comparison operators 26
Control Structures 2-3, 6-7, 23-25
Copyright 1-2, 4, 8-9, 17
csh 5, 33
curly braces 18
current working directory 10, 29, 34
do 2-6, 8-16, 18-20, 22, 24-31, 33
done 2, 6, 11-12, 18, 22, 24-25, 27-28
dot 29
double quotes 13, 15
down arrow 31
echo 5-7, 11-12, 14-16, 18-20, 22-25,
27-29, 31-34
elif 2, 18, 23
else 2, 9, 18, 23-24
emacs 3, 6, 10, 29
enumerated characters 16
esc-b 31
SKSH Amiga Shell Page 36 User's Guide
esc-f 31
excellence! 8, 29
executable 26
Executing Commands 2, 10
expr 2, 7, 18, 21, 23-27
extending SKsh 18
fi 2-4, 6-7, 9, 11-32, 34-35
File Name Mapping 2, 16, 29, 35
Filename Completion 2-3, 31, 34-35
for 1-26, 28-35
force 20
function 2-3, 6-7, 17-22, 25, 27-28, 30-32
function name 19
functions 2-3, 7, 17-19, 28, 30
history 2-3, 5, 7, 10, 31-33
HISTSIZE 31-32
I/O Redirection 2-3, 11
if 2, 4, 6-7, 9-10, 12-16, 18-21, 23-
30, 32-35
IFS 15
inc 4, 6-8, 12-14, 16-17, 22, 25, 27,
30, 34-35
index parameters 25
input 6, 11, 19, 24, 28
internal field separator 15
ksh 1, 3, 5-6, 9, 13, 19
Lattice 8-9
line editing 2-3, 31, 33-34
list of aliases 17
local 3, 7, 18, 28, 30
more input 19
newlines 12, 15, 30
number of parameters 15, 19
parameter list 19
Parameter Substitution 2, 15, 21
parameters 3, 6-7, 14-20, 25, 27
path 16, 18, 21-22, 29-30, 34
Pipe Lines 2, 12
pipeline 6
PNPC 33
Priority 2, 20
range of characters 16
read 6, 9, 11-12, 21, 24, 26, 28, 30
readable 26
return code 23-24, 26
reverse search 31-32
right arrow 31
secondary SKsh prompt string 19
semicolon 10
set of characters 16, 21
sh 1-25, 27-35
shift 18-19
simple command 6, 11-12
simple operators 26
SKSH Amiga Shell Page 37 User's Guide
single parameter 15
single quotes 13, 15
slash 13, 29, 35
sleep 10, 24
slow script files 18
string 2, 10, 13-16, 19, 21, 26, 30-31,
33
sub shell 28
subshell 6, 28, 30
tabs 15
test expression 2, 23-24, 26-27
then 2, 6, 18, 23-24, 26-27, 29, 31, 34
token 21
unalias 17
up arrow 31-32
variable 2-3, 7, 13-15, 18-19, 21-22, 24-
25, 27-33
which 3, 6-8, 13-16, 20-22, 24, 26, 29,
32
while 2, 6, 11, 18, 24-27
white space 13, 15
Wildcards 2-3, 8, 16
writable 26
[ ] 16, 26
^a 31
^b 31
^d 31
^e 5, 31
^f 31
^h 31
^k 31
^l 5, 31
^m 31
^n 31
^o 31-32
^p 31-32
^r 31-32
{ } 28
SKSH Amiga Shell Page 38 User's Guide