Introduction
------------
With UNICOS 8 the standard command and programming language shell
is the POSIX
shell, i.e. /bin/sh is the POSIX shell, not the Bourne shell. The
POSIX shell
is functionally equivalent to the Korn shell, so much so that at
UNICOS 8 they
are one and the same binary i.e. file /bin/ksh is a link to file
/bin/sh, and
both contain the binary for the POSIX shell. The Bourne shell is
the default
shell under UNICOS 7, where file /bin/ksh contains the Korn shell
binary and
file /bin/sh contains the Bourne shell binary. All Bourne shell
scripts should
work unchanged under the POSIX shell, since the features of this
shell are a
superset of those of the Bourne shell.
In the past users have generally used the Bourne shell for Batch
work and the
C shell for Interactive work. This is because the Bourne shell,
on UNICOS at
least, is more efficient than the C shell and allows redirection
of the
standard error file. The C shell with its command history and "alias"
capabilities is more suited to interactive use. The Korn shell
attempts to
incorporate, and in many ways improve upon, some of the useful
C shell
features, while still allowing Bourne shell scripts to execute
unchanged.
This article will mainly concentrate on the new features of the
POSIX shell
over and above those provided by the Bourne shell. These include:
command
history, command editing, tilde substitution, aliases, exporting
of aliases
and functions, the "ENV" file, the ability to do integer arithmetic
and to use
array variables, regular expressions and pattern-matching operators,
the
"select" control structure, and extra shell variables and special
built-in
commands.
Command History
---------------
The POSIX shell, like the C shell, keeps a record of the most recently
typed
commands. The number of interactive commands recorded is determined
by the
shell variable HISTSIZE, which, if not set, defaults to 128. A
record of the
commands is kept in a file determined by the shell variable HISTFILE,
which
if not set, defaults to $HOME/.sh_history, though on the Cray computers
at
ECMWF this variable has been set to $TMPDIR/.sh_history. To list
the last 16
commands input to the shell all you need to type is:
history (or h, both are aliases for fc -l)
To see more history, just supply the amount as a negative number, e.g.
h -30
Command Editing
---------------
On the Cray computers at ECMWF the shell variable VISUAL has been
set to
/usr/bin/vi. This means that while typing an interactive command
it is
possible to correct errors by using the POSIX shell's built-in
vi-like editor
(there is also a built-in emacs-like editor, though this will not
be described
here). To enter the editor command mode you need to press the ESCAPE
key. You
can then use many of the normal "vi" commands to correct the line
of text, and
the press the RETURN key to execute the modified command. The "vi"
commands
include:
[count]h to position
1 (or count) character(s) to the left
[count]l to position
1 (or count) character(s) to the right
i
to insert text; press the ESCAPE key to terminate insert mode
[count]x to delete
1 (or count) character(s)
[count]r to replace
1 (or count) character(s)
cw
to replace a word
u
to undo the last modification
U
to undo all modifications
*
to do filename generation
\
to do filename completion
While in editor command mode it is possible to abandon the command
being
typed, and edit any of the commands in the history file. This is
done again
by using standard "vi" commands, which include:
[count]k to fetch
the previous (count) command
[count]- same
as [count]k
[count]j to fetch
the next (count) command
[count]+ same
as [count]j
[count]G to fetch
command number count. If count is not specified
then it defaults to the least recent history command,
unlike in "vi" where G means the last line in the file.
/string
to search backward in the history file for a previous
command containing string (less recent). string is
terminated by the RETURN key. If string is preceded by a
caret '^' then the matched command must begin with string.
?string
to search forward in the history file (more recent).
Another way of editing and re-executing commands from the history
file is to
use the built-in command "fc". An alias is available, called "r"
for "repeat",
which uses "fc". Some examples should make it easy to see how to
use it:
r
this will repeat the previous command
r 122
this will repeat command number 122
r cf
this will repeat the last command beginning
with the string "cf"
r abc=xyz
this will repeat the last command, replacing
the string "abc" within the command by the
string "xyz"
r lib="-l lib" cc
this will repeat the last command beginning
with the string "cc", replacing the string
"lib" within the command by the string "-l lib"
Tilde "~" Substitution
----------------------
Like the C shell, the POSIX shell allows you to specify a user's
$HOME
directory by using the string "~userid". If userid is not a valid
user
identifier then no substitution is performed. A ~ by itself or
in front of a
/ is interpreted as the current user's $HOME directory. A ~ followed
by a +
or - is interpreted as $PWD and $OLDPWD, respectively.
Aliases
-------
POSIX shell aliases are similar to, but different from, C shell
aliases. The
syntax for defining them is different and they do not allow arguments.
Aliases
can be exported to child processes and you can also set up "tracked"
aliases,
this being the POSIX shell equivalent of the C shell hashing mechanism.
The
format for defining an alias is:
alias [-t] [-x] name=command
The '-x' makes this an exported alias, and the "-t" makes it a tracked
alias.
Without the "name=command" portion the command lists the aliases
currently in
effect.
Aliases are frequently used as short forms for full path names.
A tracked
alias has as part of its initial value the full path name of the
command as
defined by the PATH variable and becomes undefined each time the
PATH variable
is reset. The alias is tracked so that the next subsequent reference
will
redefine the value. Aliases can be removed by using the special
command:
unalias name
The following example shows how to set up and list some aliases:
You type: Response:
alias -x ls="ls -l "
alias
ls=ls -l
alias -t dir="ls -CF "
alias
dir=ls -CF
ls=ls -l
alias -x
ls=ls -l
alias -t
ls=/bin/ls
PATH=$PATH:$HOME/bin
alias -t
none
Exporting Aliases and Functions and the "ENV" File
--------------------------------------------------
As mentioned above, aliases may be exported to POSIX shell child
processes by
defining them with the "-x" option specified. Functions may be
exported by
defining them and then using the "-f -x" options of the special
command
"typeset" e.g.:
cdls( )
{
cd
$1
ls -la $1
}
typeset -fx cdls
The "typeset" special command has many uses and will be described
later in
this article. The first line of the above function definition "cdls(
)" is
similar to the way the C language defines a function; it could
be replaced by
the more Fortran-like syntax "function cdls", which is equivalent.
Unless specified, aliases and functions, as with normal shell variables,
are
not exported to child processes. To explore this further we will
explain the
steps which are followed when the POSIX shell is invoked and shell
scripts are
executed.
If your login shell is set to the POSIX shell, or if you run a batch
job under
the default (POSIX) shell, then the following sequence of events
takes place.
The file /etc/profile is read by the shell and the commands within
this file
are executed. Next the file $HOME/.profile is read and the commands
executed.
Usually $HOME/.profile has in it a reference to the file $HOME/.user_profile.
This file is also read and its commands executed. After this the
POSIX shell
then checks the ENV shell variable, which by default on the ECMWF
Cray
computers is set to /etc/sh_env. If it is set and the file it references
is
readable then the shell executes the commands stored in the file.
/etc/profile is set up by ECMWF systems staff and contains commands
to set up
such global shell variables as TERM - terminal type, DISPLAY -
display console
name, ECLIB - the location of the eclib library, TEMP - the name
of the user's
directory in /tmp etc.
$HOME/.profile is owned by the user and therefore can be modified
by him.
However in general it should not be modified, as the next file
is available for
that purpose.
$HOME/.user_profile is owned by the user and can be tailored by
him to contain
any commands he wishes to execute automatically at login time or
at the
beginning of batch job execution. This may be used to set up other
global shell
variables, modify the PATH parameter, or set up private aliases
and shell
functions, though these are better done in an "ENV" file.
/etc/sh_env is set up by ECMWF systems staff and this is the value
of the ENV
shell variable. The file contains alias and function definitions
which are
deemed to be useful for all users. There is a reference within
this file to the
file $HOME/.sh_env. If this file exists and is readable then the
commands
within it are also executed.
$HOME/.sh_env is owned by the user and can be tailored by him to
contain any
private aliases and functions or global shell variables.
As can be seen there are quite a few files to read and execute.
The "ENV" files
would appear to be surplus to requirements, but these files, /etc/sh_env
and
$HOME/.sh_env are special in that not only are they read at login
or start of
job time, but they are also read and the commands executed whenever
a new shell
is invoked, whereas the various "profile" files are only read once.
To see how
this matters we need to look at the steps involved when a new shell
is invoked
and when a child shell is invoked.
If a script is executed by name then it normally runs as a forked
process of
the current shell and all exported variables, aliases and functions
are
available to this forked process. If the the script is run via
the "sh" (or
"ksh") command, or if it has execute but not read permission, or
if it has a
line saying "#! /bin/sh" (or "/! /bin/ksh") as its
first record, then a new
shell (not a forked shell process) is started and although the
exported
variables are available, the exported aliases and functions are
not. However in
this case, commands in the file specified by the ENV variable are
executed when
the new shell starts up. From this one can see that it is best
to define
exported aliases and functions in the file $HOME/.sh_env, rather
than in
$HOME/.user_profile, so that they are available to all subsequent
scripts, not
just those executed by forked shell processes.
If you have a lot of shell functions, putting them in the $HOME/.sh_env
file
becomes unwieldy. It may also affect the time it takes to start
new shells, as
the file has to be read each time and the functions loaded. The
command
"autoload function" circumvents these problems. "autoload" is a
standard alias
for the ubiquitous "typeset" special command, the alias being
"autoload='typeset - fu'". This tells the shell that the function
exists but is
undefined. When the POSIX shell encounters a reference to this
function it then
searches the set of directories specified by the FPATH environment
variable
(whose format is the same as PATH), for a file with the same name
as the
function. This function is then loaded into the shell. If, for
example, your
FPATH variable is set up in your $HOME/.user_profile as:
FPATH="$HOME/sh_functions"
Then the first reference to any function specified on an "autoload"
command
will cause the shell to look into the directory $HOME/sh_functions
to see if a
file with the same name as the function exists. The function definition
will
then be loaded into the shell and will be used directly from the
shell from
then on. Initially this variable FPATH is set in /etc/sh_env to:
FPATH="/usr/local/bin/sh_functions"
This directory contains some functions which are of general use
and which are
defined as "autoload" functions in /etc/sh_env also. If you want
to add your
own functions, it is suggested that you put each function definition
in a
separate file in a directory called $HOME/sh_functions, define
each function as
an "autoload" function (or if you wish them to be exported use:
autoload -x) in
your $HOME/.sh_env file, and define the FPATH variable in your
$HOME/.user_profile file as
FPATH="$FPATH:$HOME/sh_functions"
To see what functions are defined use the functions command (an
alias for
typeset -f), and to delete a function definition use unset -f function.
This
will erase the function from the shell's memory; however, autoloaded
functions
are still remembered and any reference to one will cause it to
be reloaded.
Functions help to simplify scripts by making them more modular.
Since they
reside in the shell's memory (however see the description of autoloaded
functions above), they execute quickly and do not run as a separate
process,
which is the case with script files. A function which has the same
name as a
script or executable binary takes precedence over these. The command
precedence
of the POSIX shell is:
Keywords such as "if", "while", "else" etc.
Aliases
Built-in special commands such as "cd", "print", "set" etc.
Functions
Scripts and executable
binaries
Integer Arithmetic and Array Variables
--------------------------------------
The ability to do integer arithmetic is provided by the POSIX shell
with the
special command "let". Constants are of the form [base#]n,
where base is a
decimal number between 2 and 36 representing the arithmetic base
and n is a
number in that base. base# is optional and if omitted then base
10 is assumed,
e.g. 16#1f is decimal 31 and 2#111 is 7.
An arithmetic expression uses the same syntax, precedence and associativity
of
expression as in the C language. All integral operators, other
than ++, - -, ?:
and , are supported, including +, -, *, /, %, >>, <<, !,
~, &, |, ^, &&, ||, >,
<, >=, <=, !=, ==, +=, -=, *=, /=, %=. Named parameters can
be referenced by
name within an expression without using the parameter substitution
($) syntax.
When a named parameter is referenced, its value is evaluated as
an arithmetic
expression, unless it has been specified to be of integer type
using the "-i"
parameter of the "typeset" special command.
Because many of the arithmetic operators need quotation marks, to
prevent them
from being interpreted by the shell, an alternative form of let
" .... " is
available, in the form of (( .... )). The result of an arithmetic
expression
can be obtained using the form $(( .... )). Do not confuse this
with
$(command), which is analagous to using back-quotes (`) to substitute
the
output produced by running command. One possible problem with using
"let" or
"(( .... ))", which also exists with the expr command, is that
an expression
which evaluates to 0 (zero) sets the shell status variable "$?"
to a non-zero
value, which will abort the shell if the "set -e" command has been
used. This
problem does not occur with the "$(( ... )) construct. Some examples
should
make this clearer.
# Create a function to see if a value is an odd number
# ----------------------------------------------------
is_odd()
{
# Return TRUE status (0) if argument is an odd number
((($1 % 2) == 1))
}
# Show different ways of setting c to 4 and printing
# --------------------------------------------------
expand="(a + b)"
typeset -i a=8#12
b=2
let "c = expand % 8"
echo $c
4
((c = expand % 8))
echo $c
4
c=$((expand % 8))
echo $c
4
echo $((expand % 8))
4
# Show how status depends on value and construct
# ----------------------------------------------
((n = 1 + 1)) && print "n = $n, status = $?"
n = 2, status = 0
((n = 1 - 1)) || print "n = $n, status = $?"
n = 0, status = 1
n=$((1 - 1)) && print "n = $n, status = $?"
n = 0, status = 0
# Obtain the time and print minutes since midnight
# ------------------------------------------------
hr=$(date +%H)
mn=$(date +%M)
sc=$(date +%S)
secs=$((sc + 60 * ( mn + 60 * hr )))
print $hr $mn $sc $secs
15 21 04 55264
The POSIX shell supports the use of one dimensional array variables.
Array
subscripts can be constants, variables or expressions in the range
0 to 1023.
Arrays need not be declared. Whole arrays can be assigned values
using the "-
A" parameter of the special command "set", while individual elements
can be
set as normal. Any reference to a named parameter with a valid
subscript (0 -
1023) is legal and an array will be created if necessary.
Referencing an
array without a subscript is equivalent to referencing element
0 of the array.
For example, exporting array is equivalent to exporting array[0],
i.e. only
the first element, not all elements of the array. To reference
an array
element, other than in an expression, it is necessary to use the
construct
${array[element]}. The construct ${array[*]} or ${array[@]}
gives the value
of each element separated by a space. The construct ${#array[*]}
gives the
number of valid elements of array. A strange feature of POSIX shell
arrays is
that if an array element has not been assigned, then it does not
exist. If
this value were, for example, 4, then this would not necessarily
mean that
elements 0, 1, 2 and 3 of the array existed, just that 4 elements
in the range
0 to 1023 existed. Normally a script would be written to use consecutive
elements, starting at 0. Some examples should make this clearer:
# Run 4 resolutions with associated "n" and "s" options
# -----------------------------------------------------
set -A nvals 1 22 53 75
set -A svals 7 16 31 96
set -A resolution T21 T63 T106 T213
code[0]="OK - no problem"
code[1]="ERROR - correct and rerun"
n=0
while [ $n -lt ${#resolution[*]} ]
do
./run_spm -n ${nvals[$n]} -s ${svals[$n]} ${resolution[$n]}
echo ${code[$?]}
((n += 1))
done
# Create a 10 element array of random numbers in range
0 - 31
# -----------------------------------------------------------
RANDOM=$$
# set the random number generator seed
integer i=0
# integer is an alias for "typeset -i "
while ((i < 10))
# note - arithmetic expression used
do
((ran[i] = RANDOM % 32))
print "Random number $i = ${ran[$i]}"
((i += 1))
done
# Create a 3 element array with "funny" element numbers
# -----------------------------------------------------
odd_val[3]="value 0"
odd_val[13]="value 13"
odd_val[23]="value 23"
echo "number of elements of odd_value = ${#odd_value[*]}"
number of elements of odd_value = 3
echo "number of characters in element 13 = ${#odd_val[13]}"
number of characters in element 13 = 8
echo "all = ${odd_val[@]}"
# @ is like * but preserves spaces
all = value 0 value 13 value 23
Regular Expressions and Pattern-matching Operators
--------------------------------------------------
The POSIX shell, like the Bourne shell has the concept of "wildcard"
characters, (*, ? and [ ]). However the POSIX shell goes
much further, in that
it allows regular expressions to be used. This gives it very
powerful string
matching capabilities, similar to those of UNIX utilities such
as awk(1),
egrep(1), sed(1) and others, although the syntax is different.
In fact since
the shell allows extended regular expressions, it is more powerful
in this
respect than "sed", which only allows normal regular expressions.
Regular
expressions can be difficult to understand and it is beyond the
scope of this
article to explain them. The books mentioned at the end give
detailed
explanations. A few simple examples are given here, just to show
what may be
done:
# Return a good status (0) if the argument contains
only digits
# -------------------------------------------------------------
isnumber()
{
[[ $1 = +([0-9]) ]]
}
# Return a good status (0) if the argument contains
only letters
# -------------------------------------------------------------
isalpha()
# Return TRUE status if argument is a word
{
[[ $1 = +([a-zA-Z]) ]]
}
read data
if isnumber $data ; then
print $data is a number
elif isalpha $data ; then
if [[ $data = [A-Z]* ]] ; then
print "$data begins with an upper case letter"
else
print "$data begins with a lower case letter"
fi
else
print "$data is neither a number nor a word"
fi
Notice in the above example that the test format used above is "if
[[ condition
]]", rather than the old format "if [ condition ]". This new POSIX
shell test
format allows regular expressions to be used on the right-hand
side. The old
format does not allow regular expressions, but allows for Bourne
shell
compatibility.
There are a set of pattern-matching operators #, ##, % and %%,which
allow
patterns to be stripped from strings, contained within shell variables.
The
classic use of these are to strip off components of pathnames.
The operator
${variable#pattern} will, if pattern matches the beginning of the
value of
variable, delete the shortest part that matches and return the
rest. Operator
${variable##pattern} is similar, but this time deletes the longest
part that
matches. ${variable%pattern} and ${variable%%pattern} are
also similar, but
this time the match is at the end of variable's value not the beginning.
Again,
to learn more in detail about these consult one of the books listed
below. The
following are examples of how they can be used:
# Obtain the last element of a pathname (i.e. the filename)
# ---------------------------------------------------------
basename()
# see basename(1)
{
print ${1##*/}
# to remove all but the last element
}
# Obtain the directory part of a file's pathname
# ----------------------------------------------
dirname()
# see dirname(1)
{
print ${1%/*}
# to remove last element only
}
# For Fortran (.f) or C (.c) files return the object
name (.o)
# ------------------------------------------------------------
objname()
{
print ${1%@(.f|.c)}.o
# to produce an object filename
}
SCRIPT=$(basename $0)
for file in *.f *.c
do
if [[ $file = *.f ]] ; then
cf77 $file
else
cc $file
fi
print "$SCRIPT: SRC = $file, OBJ = $(objname $file)"
done
Notice in this example that the "*.f" in the "for" statement expands
to all
filenames in the current working directory which have a ".f" suffix".
However
the "*.f" in the "if" statement does not. It is a regular expression
and means
any pattern that ends with a ".f" suffix.
The "select" Control Structure
------------------------------
The "select" control structure provides a simple method for creating
menus for
interactive scripts. The shell sends menu items to the standard
error file and
prompts the user for a selection. The structure is as follows:
select identifier in words
do
commands
done
Typically the words are the names of the menu items. Select presents
each word
(which can be a phrase) preceded by a menu number and then prompts
the user for
input. The prompt used is defined by shell variable PS3, which
defaults to "#?"
if not set. If the user enters a number corresponding to one of
the menu items,
the POSIX shell sets identifier to the word corresponding to that
item number.
If the user presses the RETURN key without typing anything, the
menu and prompt
are displayed again. If the user types something other than a menu
number, the
identifier is set to null. The user's input is saved in the shell
variable
REPLY so that if the user entered an invalid response it is possible
to find
out what was typed.
A simple example should make this clear:
PS3="Enter your selection: "
echo "
COMMAND MENU \n"
select choice in "Date & Time"
"Users Logged-in" "Files" "Exit"
do
case $choice in
"Date & Time")
date
;;
"Users Logged-in")
who
;;
"Files")
ls
;;
"Exit")
print "End of selection menu"
exit
;;
*)
echo "Invalid selection: $REPLY"
;;
esac
done
Executing this produces the following:
COMMAND MENU
1) Date & Time
2) Users Logged-in
3) Files
4) Exit Menu
Enter your selection: 1
Tue May 10 07:43:33 GMT 1994
Enter your selection: 4
End of selection menu
New Shell Variables and Built-in Commands
-----------------------------------------
The POSIX shell has several new variables that can be used in scripts,
including:
ERRNO The value of errno as set by the most recently
failed system call.
LINENO The number of the current line within the script or
function being
executed.
OLDPWD The previous working directory set up by the cd command.
RANDOM A random number, uniformly distributed between 0 and
32767.
REPLY The input given to the select statement and to
the read statement,
when no arguments are
supplied.
SECONDS The number of seconds that have elapsed since the shell
was invoked.
New built-in commands include:
cd [arg]
cd old new
The first form is the "normal" change directory command, if arg
is "-" then the directory is changed to the previous directory.
In the the second form cd substitutes the string new for the
string old in the current directory name and tries to change to
this new directory.
fc [-e ename] [-n] [-l] [-r] [first
[last] ]
fc -e - [old=new] [command]
In the first form, a range of commands from first to last is
selected from the last HISTSIZE commands that were typed at the
terminal. The arguments first and last may be specified as a
number or a string. A string is used to locate the most recent
command beginning with the string. A negative number is used as
an offset from the current command number. The "-l" flag causes
the command(s) to be listed at the terminal. Otherwise the editor
ename is invoked on a file containing these commands. If ename is
not supplied then the value of FCEDIT is used. When editing is
complete, the edited commands are executed. Flag "-r" reverses
the order of the commands and "-n" omits the line numbers when
listing them.
In the second form the command, which can be a string or a
number, is re-executed after the substitution old=new is
performed (see earlier).
print [-R] [-n] [-p] [-r] [-s]
[-u [n] ] [arg ....]
This is the shell output mechanism and can be used instead of
echo(1). For more information see the manual page for ksh(1).
read [-p] [-r] [-s] [-u [n] ] [name?prompt]
[name ....]
This is the shell input mechanism. For more information see the
manual page for ksh(1).
typeset [±H] [±L [n] ] [±R
[n] ] [±Z [n] ] [±f] [±i [n] ]
[±l] [±r]
[±t]
[±u] [±x] [name[=value]] ....
This sets attributes and values for shell variables.
Flag "-L" left justifies and removes leading blanks from value.
If n is nonzero, it defines the width of the field, otherwise the
first assignment determines the width. When name is assigned a
value, it is filled with trailing blanks, or truncated if
necessary. Leading zeros are removed if flag "-Z" is set.
Flag "-R" right-justifies the field.
Flag "-f" indicates that name is a function and no assignment may
be specified. In this case the only other valid flags are "-t" to
turn on tracing for the functions, "-u" to undefine (autoload)
the function and "-x" to export the function.
Flag "-i" specifies that name is an integer of base n.
Flag "-l" converts all uppercase characters to lowercase.
Flag "-u" converts all lowercase characters to uppercase.
Flag "-r" specifies that name is read-only.
Flag "-x" marks the given name(s), for automatic export to the
environment of subsequently executed commands.
Using a "+" instead of a "-" turns the flag off.
The following examples demonstrates some of these new commands:
# Print (the number 12 in Decimal, Octal and Binary
# -------------------------------------------------
typeset -i8 octal_number
typeset -i2 binary_number=12
decimal_number=12
octal_number=$decimal_number
print "$decimal_number $octal_number $binary_number"
12 8#14 2#1100
# Input a username, get the corresponding id and print both
# ---------------------------------------------------------
typeset -R10 username
typeset -R6 id
typeset -u upper
while :
# Loop until "exit" is input.
do
read uid?"Username? "
username="$uid"
upper="$uid"
if [ "$upper" = "EXIT" ] ; then
print "Finished"
break
fi
id=$(grep "^$uid:" /etc/passwd | cut -f3 -d:)
print "$username $id"
done
Username? abc
abc 123
Username? vwxyz
vwxyz 1370
Username? Exit
Finished
Conclusion
----------
The POSIX shell has many new features over and above those of the
Bourne shell.
It contains features which make it more suitable for interactive
use than the C
shell. In essence there is now one shell which is suited both to
interactive
and batch use and which will continue to run existing Bourne shell
scripts.
However it is not downwardly compatible with the Bourne shell and
any use in a
script of the new features described here will make that script
unusable under
the Bourne shell, unless, of course, the system posesses a Korn
shell, in which
case you should be able to prefix the script with a record stating
"#!
/bin/ksh", causing the Bourne shell to start a Korn shell to execute
the
script.
UNICOS 8 is running on the YMP-EL at ECMWF. It will also be the
operating
system running on the YMP-2E/T3D machine and will eventually become
the
production system on the C90.
To use the POSIX shell as described here you should copy the file
"/usr/local/src/public/profile" to the file "$HOME/.profile" and
tailor
"$HOME/.user_profile" and "$HOME/.sh_env" to your requirements.
You can print
the /etc/profile and /etc/sh_env files to see what has been set
up by default
and you can print any of the files in /usr/local/bin/sh_functions
to see what
functions are available. Under UNICOS 8 to make the POSIX shell
your default
interactive shell you should use the command:
chsh $USER /bin/sh
Although this article has concentrated on the POSIX shell under
UNICOS 8, most
of this information also applies to the Korn shell, "/bin/ksh",
under UNICOS 7
and under the IRIX operating system on the Silicon Graphics workstations
at
ECMWF. The Korn shell is not available on the SUN workstations
at ECMWF.
One slight problem with the Korn shell under UNICOS 7 is that it
does not
support the "-S" flag of the "set" special command, whereas the
POSIX shell
under UNICOS 8 does.
The purpose of this article is to show some of the new features
that can be
used with the POSIX shell. It is not intended as a reference manual.
To obtain
further information, read the "man" page for ksh(1), or better
still, read one
of the books describing the Korn shell such as:
"The Korn Shell User & Programming Manual" by Anatole
Olczak (Addison-Wesley)
"The Kornshell Command & Programming Language" by Morris
I. Bolsky
& David G.
Korn
"Learning the Korn Shell" by Bill Rosenblatt (O'Reilly &
Associates)
"A Practical Guide to Unix System V" by Mark G. Sobell (Benjamin/Cummings)
- Neil Storer
Original
published in the ECMWF Newsletter, No. 66 (Summer 1994)
Minor
update (ATL): 10.08.94