Using the GNO Shell More Productively
And then one day, hooray! Another way for gnomes to say hooray!
-- Syd Barret, The Gnome
What Does This Command Do?
If you are unfamiliar with what a
particular command actually does or what arguments it accepts,
you can check quickly by using the electronic manual. GNO/ME
includes a utility called man which displays the manual
pages for a command whose name you supply as an argument. The
man
utility uses another utility called more to actually
display the pages nicely on the screen.
Option Arguments
As mentioned in
,
arguments are passed to a command to extend its
usefulness. The arguments presented in the last chapter were
words, such as foo, bar and
foo.c. Standards exist under UNIX for
programs to accept command-line option arguments. Option
arguments (as the name suggests) are optional. There are two
standards, short options and long options. Short options are
characters that represent commands, whereas long options contain
the entire option name.
Consider the following output of the CATALOG command
from ProDOS:
/DEV
NAME TYPE BLOCKS MODIFIED CREATED ENDFILE
FINDER.DATA $C9 1 21-OCT-91 22:38 14-APR-90 18:24 260
FINDER.ROOT $C9 1 22-OCT-91 17:12 6-OCT-91 15:40 82
GENESYS DIR 1 21-OCT-91 23:37 25-APR-91 15:46 512
GSBUG DIR 1 21-OCT-91 23:38 19-JUL-90 16:48 512
MERLIN DIR 2 22-OCT-91 2:50 30-APR-91 20:21 1024
LIFEGUARD $B3 73 4-SEP-87 4:51 25-DEC-89 20:22 36608
ORCA DIR 2 22-OCT-91 17:12 14-SEP-89 18:27 1024
GNO DIR 2 22-OCT-91 17:12 13-AUG-91 16:36 1024
FAST.ANIM DIR 2 21-OCT-91 23:44 11-MAY-91 10:50 1024
MICOL DIR 2 22-OCT-91 3:10 14-JAN-90 2:46 1024
SRC DIR 1 21-OCT-91 23:44 7-AUG-91 20:30 512
NIFTYLIST DIR 2 21-OCT-91 23:44 29-JUL-91 4:04 1024
MCSRC DIR 1 21-OCT-91 23:45 7-AUG-91 20:34 512
BLOCKS FREE:43923 BLOCKS USED:21185 TOTAL BLOCKS:65108
It is impossible to get any variation in
the format of this output. While the GNO/ME utility ls
serves the same purpose as the command CATALOG
from Applesoft BASIC, it has a wide number of options which can tailor the
output to specific needs. Here is how ls can be used to
give similar output to the CATALOG command:
gno% ls -l
:dev
total 45k
drw--rd 0000 dir 512 Oct 21 23:45 1991 MCSrc
drw--rd 0000 dir 1024 Oct 21 23:44 1991 NiftyList
drw--rd 0000 dir 1024 Oct 21 23:44 1991 fast.anim
drw--rd 0000 dir 512 Oct 21 23:37 1991 genesys
drw--rd 0000 dir 1024 Oct 22 17:29 1991 gno
drw--rd 0000 dir 512 Oct 21 23:38 1991 gsbug
drw--rd 0000 dir 1024 Oct 22 02:50 1991 merlin
drw--rd 0000 dir 1024 Oct 22 03:10 1991 micol
drw--rd 0100 dir 1024 Oct 22 17:28 1991 orca
drw--rd 0000 dir 512 Oct 21 23:44 1991 src
The -l
short option argument tells ls to format the
output in long format. ls supports only short options.
If ls did support long options,
the above command could be changed to ls +format-long.
This is clearly more descriptive of what function ls
will perform. For users to new to the UNIX environment,
long format options are more user-friendly. However, advanced UNIX users prefer
short options because of their brevity.
As indicated above, ls has a wide
number of options available to format the output. Use the command
"ls -?" to get a short list of these
options. It is left as an exercise for the user to discover how
these options affect the output of ls. For a complete
description of the ls command and its options use the
command man ls.
As an example of the usage and importance
of long options, the following is the result of the +help
option given to the coff utility.
Note the use of both short and long options:
coff [-OPTIONS] filename [segment..] [loadsegment..]
OPTIONS DESCRIPTION
-v [+version] display coff's version number
-D [+default] disable default options
-d [+asm] dump segment body in 65816-format disassembly
-T [+tool] interpret Toolbox, GS/OS, ProDOS, ROM calls
-x [+hex] dump segment body in hex (can be used with '+asm')
-l [+label] print expressions using labels (default is offsets)
-t [+infix] display expressions in infix form
-p [+postfix] display expressions in postfix form (default)
-m [+merlin] format of '+asm' to use merlin opcodes (default)
-o [+orca] format of '+asm' to use orca/m opcodes
-a [+shorta] assume 8-bit accumulator for disassembly
-i [+shorti] assume 8-bit index registers for disassembly
-s [+header] dump segment headers only
-n [+noheader] do not print segment headers
-f [+nooffset] do not print offset into file
-h [+help] print this information, then quit
filename name of file to dump
[segment] names of segments in file to dump
[loadsegment] names of load segments in file to dump
The long options are much more descriptive,
and provide a very easy way to remember options of programs. If
an option passed to a shell utility program is not understood by
that program, you will generally receive an error message stating
that the option is not understood. If the program is
user-friendly, a brief list of supported options will also be
displayed.
Entering Multiple Commands
It is possible to give multiple commands to
the GNO shell for processing. To execute multiple commands, place
a semi-colon, ";", between them. The commands will be
executed sequentially in the order they are entered on the
command-line. Take care not to exceed the 4096 character
command-line buffer. It is possible to execute multiple commands
at the same time, this feature is discussed in
.
As an example,
to run the echo command and the ls
command in succession, enter the following on the command line:
% echo Running ls ; ls -l
The output of the preceeding command will
display the string "Running ls" followed by the output of the
"ls -l" command.
Using Aliases
gsh provides a built-in command,
alias, which
allows any command you would type on the command-line to be
renamed. You are not limited to renaming a single command name.
Rather, you could rename an entire command-line, which could
allow you to use the name "backup" to execute the command
"backup +source /system +destination /tape.drive".
The alias command is also a very powerful means of
customizing your GNO environment to emulate other computing
environments.
To emulate the ORCA environment, the
following aliases could be entered into your gshrc file,
or a script called orca.alias that
gshrc would run:
alias copy cp
alias cat "ls -l"
alias catalog "ls -l"
alias move mv
alias rename mv
alias delete rm
alias type cat
alias prefix cd
alias create mkdir
If you alias a string containing multiple
words, you must enclose the string in quotes, as done for the
catalog alias. gsh interprets the string as one value. If
you do not include both the opening and closing quotes, the alias
command will notify you of your error.
You can view any alias' that are set by entering the
alias
command without any arguments. The setting of a
particular alias can be viewed by entering one argument
consisting of the name of the alias to view.
If you wish to remove an alias, use the command
unalias
with the aliased name as the argument. To remove
the aliases from the orca.alias
file given above, you could do the following:
%unalias copy cat catalog move rename delete type prefix create
Unlike the alias command, the unalias
command can take multiple arguments. See
for further discussion of the alias and
unalias commands.
Redirecting Input and Output
Most shell utilities write their output to
the screen. However, under GNO/ME, like ORCA, it is possible to
redirect that output to a file or a GS/OS device. The
output of the ls command above was imported into this
manual by redirecting it to a file. In addition to redirecting
the output of a shell utility, it is also possible to redirect
the input of that utility. Consider the following gsh
session:
[1]% echo this is a test
this is a test
[2]% echo this is a test > file1
[3]% cat file1
this is a test
[4]% cat < file1
this is a test
In the example above, cat takes
input from "standard input". In command 3 above, cat
takes as an argument the filename file1
and writes the contents
of that file to "standard output". Where no filename
argument is given, cat reads input from standard input and
writes the output to standard output.
In the case of command 4 above, cat
contains no arguments and therefore reads from standard input.
However, gsh interprets the "<" redirection
operator and opens the file file1
for use as standard input. Therefore, cat
will take its input from file1,
even though it thinks it is reading input from
standard input. This input redirection is transparent to the
utility, making it work with most shell utilities.
Command 2 above created a new file called
file1. If this file had existed prior to the command then it
would have been erased. It is possible to append output to the
end of the file by using the ">>"
redirection operator. Consider the following gsh session:
[5]% echo second line >> file1
[6]% cat file1
this is a test
second line
Output that is sent to "standard error",
can also be redirected. The ">&" operator
redirects standard error to a file and ">>&"
appends standard error to the end of the file. Below is a summary
of the redirection operators:
GSH Redirection Operators
stdin
stdout
stderr
redirect input from file
<
redirect output to file
>
>&
redirect output to EOF
>>
>>&
Output can be redirected to a storage
device, printer, modem, or any other valid GNO or GS/OS device.
This provides a very powerful means of communicating directly
with these devices from within gsh. One quick and dirty
example of redirection allows a background version of gsh
to be run on a terminal connected directly through the modem
serial port:
[1]% gsh < ttya > ttya >& ttya &
Pipelines
In addition to the redirection operators,
there is one additional operator which gives control over how
input and output are handled. The operator is a
pipeline, "|".
Pipelines allow the standard output of one
command to be used as the standard input to another command. This
is almost equivalent to running the first command with its output
redirected to a temporary file, then running the second command
with its input redirected from the temporary file, then removing
the temporary file. Pipelines make useful "filter" processes
where the output of one command can be sent to another command
which filters the output to whatever parameters you give the
second command. As an example, you could display all the
filenames with the character "a" in their name:
[1]% echo foo > file1
[2]% echo abc >> file1
[3]% echo aabc >> file1
[4]% echo GNO >> file1
[5]% echo standard >> file1
[6]% echo oof >> file1
[7]% cat file1
foo
abc
aabc
GNO
standard
oof
[8]% cat file1 | grep 'a'
abc
aabc
standard
Pipelines are useful when you wish to view
lines of text in a file that contain a phrase, or if you want to
connect two programs directly, bypassing intermediate files. It
is also possible to connect multiple commands with multiple
pipelines.
Pipelines are frequently used for paging
output. The coff program mentioned previously prints the
output of an OMF disassembly to the screen but does not pause when a key
is pressed. In order to pause the display, the output must be
piped through a paging utility. The ORCA shell requires that you
wait for the entire command to complete execution before the
pipeline is processed. However, GNO/ME executes both commands
concurrently which allows the coff utility to execute
while the paging utility displays the program output. GNO/ME
comes with two page utilities,
more and less.
Complete desciptions of
coff,
more, and
less
can be found in the electronic manual using the man command.
Background Execution of Commands
A major benefit of GNO/ME is multitasking.
Multitasking is a means of running multiple applications at once
(not literally but very close). On the Apple IIGS, GNO/ME
accomplishes pre-emptive multitasking by switching among
applications that are running in the background. Any GNO/ME
utility can be run in the background. Applications running in the
background generally run for the same period of time (GNO/ME
switches between applications 20 times a second).
To background a shell utility, place the "&"
character at the end of the command-line. The
GNO shell displays a unique process ID and job number for each
backgrounded command.
It is possible to use the background character "&"
to separate commands as with the ";" character.
Each command with a trailing "&"
is executed in the background.
Up to 32 processes can executed concurrently under the GNO Kernel.
Warning: When you exit the GNO Shell all
processes will be terminated including any you may have running
in the background.
Below is a sample session with background tasks:
[5] script> ps
ID STATE TT MMID UID TIME COMMAND
1 ready co 1002 0000 0:45 NullProcess
2 ready co 1007 0000 0:05 gsh
138 running co 1006 0000 0:00 ps
[6] script> cmpl +p script.c keep=script > outputfile &
[1] + 141 Running cmpl +p script.c keep=script &
[7] script> ps
ID STATE TT MMID UID TIME COMMAND
1 ready co 1002 0000 0:45 NullProcess
2 ready co 1007 0000 0:05 gsh
141 waiting co 1006 0000 0:00 cmpl +p script.c keep=script
142 ready co 100B 0000 0:00 5/cc
143 running co 100D 0000 0:00 ps
[8] script> cmpl +p script.asm keep=script1 > output2 & ps ; ls -s
[2] - 145 Running cmpl +p script.asm keep=script1 &
ID STATE TT MMID UID TIME COMMAND
1 ready co 1002 0000 0:45 NullProcess
2 ready co 1007 0000 0:05 gsh
141 waiting co 1006 0000 0:00 cmpl +p script.c keep=script
144 ready co 100E 0000 0:07 5/linker
145 ready co 100D 0000 0:00 cmpl +p script.asm keep=script1
146 running co 100F 0000 0:00 ps
147 ready co 1011 0000 0:00 5/asm65816
3 barf 1 outputfile 6 script.asm 1 script.root
1 foobar 19 script 3 script.c 36 script.sym
1 output2 6 script.a 6 script.mac 1 typescript
[9] script> cp script.asm script2 &
[3] 150 Running cp script.asm script2 &
[2] - Done cmpl +p script.asm keep=script1 &
[1] + Done cmpl +p script.c keep=script &
[3] - Done cp script.asm script2 &
[10] script> ps
ID STATE TT MMID UID TIME COMMAND
1 ready co 1002 0000 0:45 NullProcess
2 ready co 1007 0000 0:05 gsh
151 running co 1006 0000 0:00 ps
The first command line sends the
ps
command to the shell.
ps
lists the processes currently being executed by the
GNO kernel. The processes named gsh and
NullProcess
are always present. For a complete description of the
ps command, see
.
When a command is executing in the
background, keyboard input is not sent to it. However, output is
still treated in the same way. If the command sends output to the
standard output or standard error, the screen will become
cluttered. Try this example:
[1]% ls -l&
[2]% ls -l
Both the output of commands #1 and #2 will
be sent to the screen. After command #1 is entered and you begin
typing command #2, you will see the output of the first
"ls -l"
command being sent to the screen while you enter command #2.
Utilities which produce output should have their standard output
and standard error redirected to a file when they are executed in
the background. See
.
Executing commands in the background
hinders the performance of the Apple IIGS. This is not too
noticeable when one or two commands are being executed but
performance will degrade more noticably as more commands are
started. The Apple IIGS was not designed as a multitasking
computer so the performance of GNO/ME should be understandable.
If you have an accelerator (such as the Transwarp GS or Zip GS)
installed, performance of multiple tasks will be acceptable.
Job Control
Now that command backgrounding and
multitasking have been discussed, some more definitions can be
mentioned. A process is a command which has been submitted to the
shell for execution.
gsh contains a set of special
commands which make dealing with processes much easier. gsh
treats each command entered at the command-line as a job,
where a single job may contain multiple processes. For example:
% ls one command, one process, one job
% ls ; ps two commands, two processes, two jobs
% ls & ps two commands, two processes, two jobs
% ls | more two processes, one job
When a job is run from the shell, it can be
in several modes of operation. Jobs can be in any of three
states: "running", "stopped", or "done". A job can
be executing in either the foreground or the background.
Commands exist to place a job in any mode
of operation. When a job is run directly from a command-line it
is running and it is in the foreground. Since the command-line
cannot be accessed, two special keys have been defined:
^C kills the job and
^Z will stop the job. When the job is killed, it is
gone forever, but a stopped job can be restarted. When a job is
stopped, the kernel suspends each of the processes in the job.
Jobs that are running in the background or
have been stopped can be accessed using several built-in
commands. The bg command will place a job in the
background, placing it in the running state if necessary. The
fg
command will similarly place a job in the foreground, and the
stop
command will stop a backgrounded job. The kill command
will terminate a job.
Each time job control is accessed, a
special job status line is displayed following the command. The
first item on the left in brackets is the job number. Next is a
single character, either a '+', '-', or a blank. The '+' designates the
currently accessed job, the '-' is the previously accessed job, and all
other jobs are not specified. The
jobs
command will display a list of all jobs.
Have another look at the example in
;
now more of the notation will be understandable.
Each of the special commands,
bg,
fg,
stop, and
kill,
take an argument which specifies the job to perform the
operation on. The argument is either a number specifying the
process id, or a '%' followed by one of the following:
'+' or '-' for the current job,
a '-' for the previous job,
or a number to specify any
specific job. If nothing follows the '%' or the argument is
missing, then the current job is the default.
There is one additional way that a job may
be stopped. If the job is placed in the background and it
attempts to read from the console, the job will be stopped, and
the status line says "(tty input)" as the reason for the job
being stopped. The job should be foregrounded so that the user
may enter input to the program. It can then be placed back in the
background as necessary (with ^Z and
bg).
Working with Pathnames
To move easily to directories descended
from the home directory, gsh provides the "~"
(tilde) character. This character represents the home directory.
Therefore, if your home directory was
:hard:gno:home:root,
you could use the command
"cd ~" to
move to the home directory (note that
"cd"
without any arguments
also defaults to the home directory). To move to subdirectories
of the home directory, you could use the command
The tilde character is recognized by gsh before
the command is interpreted.
Another special sequence, "..",
when used as part of a pathname, will strip the last path between
pathname seperators. For example, the pathname
"/dev/gno/.." would be expanded to
"/dev".
The "/gno" portion of the path
is stripped as it is before the periods.
This provides an excellent way to backup into your directories.
"Backing up" is limited by the volume directory of the
device being used.
Additionally, the character "."
can be used to signify the current directory.
Pathname Expansion
Many utilities supplied with gsh
take, as an argument, a filename or filenames. The shell utilities
cat,
ls,
grep, and
cp
can take multiple filenames as arguments. If you wish to invoke any
of these utilities on filenames that have a sequence of
characters in common (ie.
AND,
APPLE,
SHK,
TXT,
FILE2,
FILE3,
etc), gsh provides special characters,
called regular expressions or wildcards, which match multiple
filenames without having to enter all filename arguments
manually.
GSH Wildcard Operators
*
Matches any string of characters.
?
Matches a single character.
[abc]
Matches any of the characters enclosed in brackets.
[^abc]
Matches any of the characters not enclosed in brackets.
[a-c]
Matches the ascending sequence of characters enclosed in brackets.
This method of matching filenames is known
as "globbing". gsh performs globbing on the word
prior to executing the command. The following gsh session
illustrates file globbing:
[1]% cd /dev/gno/utilities
[2]% ls
:dev:gno:utilities
CONV Crunch CrunchIIGS DeRez DiskCheck
DumpObj Duplicate EMACS Equal Express
Files LinkIIGS MakeBin MakeDirect OrcaDumpIIGS
Prizm ResEqual Search canon choose
clrff cmdfix coff compact count
detab dir dirff dumpfile eject
emacs.doc emacs.hlp emacs.rc emacs.tut help
init join link macgen makelib
mem online pageeject pause pwd
src
[3]% ls e*
:dev:gno:utilities
EMACS Equal Express eject emacs.doc
emacs.hlp emacs.rc emacs.tut
[4]% echo *r *m
dir Prizm mem
[5]% echo *i*
cmdfix CrunchIIGS Prizm DiskCheck Duplicate Files init
join LinkIIGS makelib MakeBin MakeDirect link dirff
dumpfile online OrcaDumpIIGS dir
[6]% echo NoMatch*
No match.
[7]% echo [a-f]*
coff canon cmdfix compact Crunch CrunchIIGS DeRez DiskCheck
DumpObj Duplicate EMACS emacs.doc emacs.hlp emacs.rc
emacs.tut Equal Express Files choose clrff count detab CONV
dirff dumpfile eject dir
[8]% echo [a-fs-t]*
coff canon cmdfix compact Crunch CrunchIIGS DeRez DiskCheck
DumpObj Duplicate EMACS emacs.doc emacs.hlp emacs.rc
emacs.tut Equal Express Files choose clrff count detab
Search src CONV dirff dumpfile eject dir
[9]% echo emacs?*
EMACS emacs.doc emacs.hlp emacs.rc emacs.tut
[10]% echo [^a-f]*
Prizm help init join LinkIIGS makelib MakeBin MakeDirect
link mem ResEqual Search src online pageeject pause
OrcaDumpIIGS pwd macgen
[11]% echo [^a-fs-t]*
Prizm help init join LinkIIGS makelib MakeBin MakeDirect
link mem ResEqual online pageeject pause OrcaDumpIIGS pwd
macgen
[12]% echo ???
mem src pwd dir
[13]% echo ?
No match.
[14]% echo "???"
???
[15]% do you have a light?
No match.
As can be seen by the above example,
character matches are case insensitive. The ProDOS file system
treats the filenames "file" and
"FILE" as the same
file. gsh recognizes this and does not detract from the
underlying file system.
File globbing makes passing arguments to
commands much easier and much more powerful. You could easily use
"*.c" as an argument in a number of ways:
[1]% ls *.C lists all filenames ending in ".C"
[2]% cc *.C compiles all files ending in ".C"
[3]% more *.C displays contents of all files ending in ".C"
Quoting Special Characters
Beginning with Apple IIgs System Software 6.0, GS/OS is
able to read files from Macintosh
computers. The Macintosh uses a filesystem known as HFS, which
allows filenames to contain any character except the colon (":").
Because a filename such as "emacs?*" is valid under HFS, care must be taken or
unexpected results will occur. The word "emacs?*" was
used as a regular expression above to specify a list of filenames
beginning with the word "emacs" and one or more
trailing characters. gsh does provide a way to pass an
argument which contains special shell characters to a command.
This is known as quoting an argument. There are three different
ways to quote an expression:
The single quote will quote everything
between the single quote marks. Thus, to display the contents of
a file on an HFS volume named "emacs?*", use the
command:
more 'emacs?*'
The double quote will quote everything
between the double quote marks except variables;
echo "emacs?* $home"
will product "emacs?* /dev/gno".
See
for more on variables.
The backslash is used to quote one
character. To pass "emacs?*" as a regular using the backslash,
one could enter the following:
ls emacs\?\*
One additional purpose of the quoting
mechanism built into gsh is to add spaces to command
arguments. Each command and its arguments is separated by a
space. Multiple spaces between arguments are treated as one
space. Thus, consider the following:
% echo a b c
a b c
% echo 'a b c'
a b c
How gsh Finds a Command
gsh has a special variable, PATH, which
specifies the directories and order of directories to search for
shell utilities. This variable is often setup in the gshrc
file although it can be changed as often as needed. The purpose
of the PATH environment variable was discussed in
.
When gsh starts up, it searches all
directories specified in the PATH environment
variable and establishes a table of all commands,
called a hash table. Because of this table, gsh
"knows" where a command is and can execute the command
much faster than searching through all directories every time the
command is entered.
The search process begins with alias names.
See .
If an alias is
found that matches the command, the alias is replaced with its
value and the command-line is again parsed. If it was not an
alias, gsh checks to see if it was a special built-in
utility. The search process then searches for the name in the
hash table. If an entry is found in the hash table, the path name
of the command is retrieved and the command is executed. If an
entry is not found, the current path is searched. If the command
name is not found, an error results.
When the PATH environment variable is
changed, gsh does not automatically recreate the command
hash table. You need to issue the command
rehash to
recreate the hash table. The more pathnames specified, the
greater the delay in starting gsh and in invoking the
rehash command.
The following shell script changes PATH
and invokes the
rehash command in one step.
echo Resetting PATH variable $PATH to $1
set path=$1
rehash
The $1 variable will be expanded with the first argument
passed to the script.
rehash
should also be used if a new utility is copied to one of the
directories specified in the PATH variable. Of course, it is
possible to specify the absolute pathname of any command, but
this is undesirable if the command is frequently used.