Appendix A. Related Shells

The fragmentation of the Unix marketplace has had its advantages and disadvantages. The advantages came mostly in the early days: lack of standardization and proliferation among technically savvy academics and professionals contributed to a healthy “free market” for Unix software, in which several programs of the same type (e.g., shells, text editors, system administration tools) would often compete for popularity. The best programs would usually become the most widespread, while inferior software tended to fade away.

But often there was no single “best” program in a given category, so several would prevail. This led to the current situation, where multiplicity of similar software has led to confusion, lack of compatibility, and — most unfortunate of all — Unix’s inability to capture as big a share of the market as other operating platforms. In particular, Unix has been relegated to its current position as a very popular operating system for servers, but it’s a rarity on desktop machines.

The “shell” category has probably suffered in this way more than any other type of software. As we said in the preface and Chapter 1, it is one of the strengths of Unix that the shell is replaceable, and thus a number of shells are currently available; the differences between them are often not all that great. We believe that the Korn shell is one of the best of the most widely used shells, but other shells certainly have their staunch adherents, so they aren’t likely to fade into obscurity. In fact, it seems that shells, Bourne-compatible or not, continue to proliferate.

Therefore we felt it necessary to include information on shells similar to the Korn shell. This Appendix summarizes the differences between the Korn shell and the following shells:

  • The System V Release 4 Bourne shell, as a kind of baseline

  • The 1988 version of the Korn shell

  • The IEEE POSIX 1003.2 Shell Standard, to which the Korn shell and other shells adhere

  • The Desk Top Korn shell (dtksh), a Korn shell with enhancements for X Window System programming, as part of the Common Desktop Environment (CDE)

  • The tksh shell, an interesting blend of ksh93 with Tcl/Tk

  • pdksh, a widely used public domain version of the Korn shell

  • The bash shell, another enhanced Bourne shell with some C shell and Korn shell features

  • The Z shell, zsh, yet another enhanced Bourne shell with some C shell and Korn shell features and many, many more of its own

  • Korn shell workalikes on desktop PC platforms

The Bourne Shell

The Korn shell is almost completely backward-compatible with the Bourne shell. The only significant feature of the latter that the Korn shell doesn’t support is ^ (caret) as a synonym for the pipe (|) character.[131] This is an archaic feature that the Bourne shell includes for its own backward compatibility with earlier shells. No modern Unix version has any shell code that uses ^ as a pipe.

To describe the differences between the Bourne shell and the Korn shell, we’ll go through each chapter of this book and enumerate the features discussed in the chapter that the Bourne shell does not support.

Chapter 1

The cd old new and cd - forms of the cd command.

Tilde (~) expansion.

The Bourne shell always follows the physical file layout, which affects what happens when you cd .. out of somewhere that was a symbolic link.

The built-in commands don’t have online help.

Some older versions of the Bourne shell don’t support the jobs command and job control, or they may require being invoked as jsh in order to enable job control features.

Chapter 2

All (i.e., the Bourne shell doesn’t support any of the history and editing features discussed in Chapter 2).

Chapter 3

Aliases are not supported.

set -o options don’t work. The Bourne shell supports the abbreviations listed in the “Options” table in Appendix B, except -A, -b, -C, -m, -p, and -s.

Environment files aren’t supported; neither is the print command (use echo instead). The following built-in variables aren’t supported:

.sh.edchar .sh.version HISTEDIT LINENO PS4
.sh.edcol COLUMNS HISTFILE LINES PWD
.sh.edmode EDITOR HISTSIZE OLDPWD RANDOM
.sh.edtext ENV LANG OPTARG REPLY
.sh.match FCEDIT LC_ALL OPTIND SECONDS
.sh.name FIGNORE LC_COLLATE PPID TMOUT
.sh.subscript FPATH LC_CTYPE PS3 VISUAL
.sh.value HISTCMD LC_NUMERIC   

Some of these variables (e.g., EDITOR and VISUAL) are still used by other programs, like mail and news readers.

Chapter 4

Extended variable names (those with a dot in them), as well as compound variable assignment are not available, nor is string concatenation with the += operator.

Indirect variables (namerefs) are not available.

The whence command is not available; use type instead.

The pattern-matching variable operators (%, %%, #, ##, etc.) and advanced (regular expression) wildcards are not available; use the external command expr instead.

Autoloaded functions are not available, and only POSIX-style functions (those defined using the name () syntax) may be used.

Command substitution syntax is different: use the older ` command ` instead of $( command ). (Some vendors have enhanced their Bourne shells to support the $( command ) notation, since it’s defined by the POSIX standard.)

Chapter 5

return may only be used from within a function.

Conditional tests use older syntax: [ condition ] or test condition instead of [[ condition ]]. These are actually two forms of the same command (see the test(1) manual page).

The logical operators && and || are -a and -o instead. Supported test operators differ from system to system.[132]

The ! keyword to reverse the exit status of a command was not in the SVR4 Bourne shell, although it may be available on your system, since it is required by POSIX.

The select construct isn’t supported. Neither is the arithmetic for loop, and there is no way to fall through from one case to another inside a case statement.

There is no equivalent for TMOUT.

Chapter 6

The SVR4 Bourne shell getopts command is similar, but not identical to, that in ksh. It does not allow options that begin with a plus sign, nor any of the advanced features described in Appendix B.

Arithmetic isn’t supported: use the external command expr instead of the $((...)) syntax. For numeric conditionals, use the old condition test syntax and relational operators -lt, -eq, etc., instead of ((...)). let isn’t supported.

Array variables and the typeset command are not supported.

Chapter 7

The following I/O redirectors are not supported:[133]

>| <> <<< <&p >&p <& n - >& n - |&

print isn’t supported (use echo instead). printf is generally available as an external command.

None of the options to read are supported, nor is the ability to supply a prompt with the first variable’s name.

The Bourne shell does not do special interpretations of pathnames, such as /dev/fd/2 or /dev/tcp/ftp.oreilly.com/ftp.

The $"..." and $'...' quoting mechanisms are not available.

Chapter 8

Job control is supported, but only if the shell is invoked with the -j option or as jsh.

The - option to trap (reset trap to the default for that signal) is not available. Instead, a missing trap indicates that the supplied traps should be reset. trap accepts only signal numbers, not logical names.

Coroutines aren’t supported.

The wait command only accepts process IDs.

Chapter 9

The ERR and DEBUG fake signals are not available. The EXIT fake signal is supported, as signal 0.

set -n takes effect even in interactive shells.

The output from tracing with set -x is not customizable (no PS4 variable).

Discipline functions are not available.

Chapter 10

Privileged mode isn’t supported. (Some Bourne shells do have it.)

The ulimit and umask commands are not as capable.

The KEYBD trap is not available.

The 1988 Korn Shell

Perhaps the most obvious shell with which to compare ksh93 is ksh88, the 1988 version of the Korn shell. This section briefly describes those features of ksh93 that are either different or nonexistent in ksh88. As with the presentation for the Bourne shell, the topics are covered in the same order as they’re presented in the rest of the book.

Chapter 1

The built-in help facilities (such as -?, --man, and so on) are not available.

Tilde substitution does not occur during variable expansion (${ var op word }).

Chapter 2

CTRL-T works differently in emacs editing mode. In ksh88, it transposes the two characters to the right of point and moves point forward by one character.

In emacs-mode, ESC ESC, ESC *, and ESC = don’t work on the first word of a command line, i.e., there is no command completion facility. The ESC # command always prepends a # character. It never removes them.

Similarly, in vi-mode, the *, and = commands don’t work on the first word of a command line, and the # command always prepends a # character. It never removes them.

Finally, there is no variable completion, the hist command is called fc, FCEDIT is used in place of HISTEDIT, and the HISTCMD variable is not available.

Chapter 3

The ENV file is sourced for all shells, and ksh88 only does variable substitution on the value of $ENV.

Alias tracking can be turned off in ksh88.

The -p option to alias is not present in ksh88, nor is the -a option to unalias.

The following built-in variables aren’t supported:

.sh.edchar .sh.match .sh.version LANG
.sh.edcol .sh.name FIGNORE LC_ALL
.sh.edmode .sh.subscript HISTCMD LC_COLLATE
.sh.edtext .sh.value HISTEDIT LC_CTYPE
Chapter 4

In ksh88, both syntaxes for defining functions produce functions with Korn shell semantics. You cannot apply the dot command to a function name.

The command search order in ksh88 is keywords, aliases, all built-in commands, functions, and then external commands and scripts. The order was changed in ksh93 for POSIX compliance.

In ksh88, undefined (autoloaded) functions are searched for exclusively along the list in the FPATH variable, and PATH is not involved.

The .paths file feature is not available.

Many of the variable substitution features described in the main text are new to ksh93. Only the following are available in ksh88: ${ name :- string }, ${ name := string }, ${ name :? string }, ${ name :+ string }, ${ name # pattern }, ${ name ## pattern }, ${ name % pattern }, ${ name %% pattern }, ${# name }, ${# name [*]}, and ${# name [@]}.

Compound variables, namerefs and the += operator for appending to a variable are not in ksh88.

The n notation in patterns is not available, nor are non-greedy matching, the use of backslash escapes in patterns, options in subpatterns, nor any of the [:...:] character classes.

The .sh.match array is not available.

Chapter 5

Exit values in ksh88 only go up to 128. Programs that die due to a signal have exit status 128 plus signal number.

There is no command built-in command. To replace a built-in, you have to use an awkward combination of aliasing, functions, and quoting.

The set -o pipefail option and the the ! keyword for reversing the sense of a test are not available. Instead of the == operator for [[...]], ksh88 uses =.

The arithmetic for loop is not in ksh88. The use of ;& for falling through cases existed in ksh88 but was undocumented. The TMOUT variable existed in ksh88, but it only applied to the shell itself, not to the select loop or the read command.

Chapter 6

The ksh88 getopts did not have the ability to specify numeric arguments to options, nor a way to specify optional arguments to options.

The built-in arithmetic only supports integers, and the ++, --, ?: and comma operators aren’t available. Numeric constants of the form base # number can only go up to base 36. There are no built-in arithmetic functions.

Only indexed arrays exist, and the maximum index is 1023.

Chapter 7

The following I/O redirectors are not supported:

<& n - >& n - <<<

TCP/IP networking is available starting with ksh88e, but you must use IP addresses.

ksh88 does not have the printf command, nor the -A, -d, -n, and -t options to read. TMOUT does not affect read.

Brace expansion and process substitution are compile-time options that are generally not available in ksh88.

Locale translation with $"..." and ANSI C strings with $'...' are not available.

Chapter 8

The disown command is not available, and neither are the -n and -s options to kill. kill -l can only be used by itself to list the available signals.

true and false are predefined aliases instead of built-in commands.

Functions and aliases are exported to shell subprocesses; this is not true of ksh93.

Chapter 9

Traps for the DEBUG fake signal are executed after each command is executed, not before.

Discipline functions are not available.

Chapter 10

The umask command only works with octal masks.

You cannot customize the built-in editors; the KEYBD fake signal does not exist.

The IEEE 1003.2 POSIX Shell Standard

There have been many attempts to standardize Unix. Hardware companies’ monolithic attempts at market domination, fragile industry coalitions, marketing failures, and other such efforts are the stuff of history — and the stuff of frustration.

Only one standardization effort has not been tied to commercial interests: the Portable Operating System Interface, known as POSIX. This effort started in 1981 with the /usr/group (now UniForum) Standards Committee, which produced the /usr/group Standard three years later. The list of contributors grew. Eventually, the effort to create a formal standard moved under the umbrella of the Institute of Electrical and Electronic Engineers (IEEE) and the International Organization for Standardization (ISO).

The first POSIX standard was published in 1988 and revised in 1996. This one, called IEEE Standard 1003.1, covered low-level issues at the system call level. IEEE Standard 1003.2, covering the shell, utility programs, and user interface issues, was ratified in September 1992 after a six-year effort. In September 2001, a joint revision of both standards was approved. The new standard, covering all the material in the two earlier separate documents, is known as IEEE Standard 1003.1-2001.

The POSIX standards were never meant to be rigid and absolute. The committee members certainly weren’t about to put guns to the heads of operating system implementers and force them to adhere. Instead, the standards are designed to be flexible enough to allow for both coexistence of similar available software, so that existing code isn’t in danger of obsolescence, and the addition of new features, so that vendors have the incentive to innovate. In other words, they are supposed to be the kind of third-party standards that vendors might actually be interested in following.

As a result, most Unix vendors currently comply with both standards. The Korn shell is no exception; it is intended to be 100% POSIX-compliant. It pays to be familiar with what’s in the standard if you want to write code that is portable to different systems.

The shell part of the standard describes utilities that must be present on all systems, and others that are optional, depending upon the nature of the system. One such option is the User Portability Utilities option, which defines standards for interactive shell use and interactive utilities like the vi editor. The standard — on the order of 2000 pages — is available through the IEEE; for information, contact the IEEE:


IEEE Customer Service
445 Hoes Lane, PO Box 1331
Piscataway, NJ 08855-1331
(800) 678-IEEE (United States and Canada)
(732) 981-0060 (international/local)
(732) 981-9667 (fax)

http://www.standards.ieee.org/catalog/ordering.html

The committee members had two motivating factors to weigh when they designed the shell standard. On the one hand, the design had to accomodate, as much as possible, existing shell code written under various Bourne-derived shells (the Version 7, System V, BSD, and Korn shells). These shells are different in several extremely subtle ways, most of which have to do with the ways certain syntactic elements interact with each other.

It must have been quite difficult and tedious to spell out these differences, let alone to reach compromises among them. Throw in biases of some committee members towards particular shells, and you might understand why it took six years to ratify the first 1003.2 standard and another five years to merge the two standards.

On the other hand, the shell design had to serve as a standard on which to base future shell implementations. This implied goals of simplicity, clarity, and precision — objectives that seem especially elusive in the context of the above problems.

The designers found one way of ameliorating this dilemma: they decided that the standard should include not only the features included in the shell, but also those explicitly omitted and those included but with unspecified functionality. The latter category allows some of the existing shells’ innovations to “sneak through” without becoming part of the standard, while listing omitted features helps programmers determine which features in existing shell scripts won’t be portable to future shells.

The POSIX standard is primarily based on the System V Bourne shell. Therefore you should assume that Korn shell features that aren’t present in the Bourne shell also aren’t included in the POSIX standard.

However, the Korn shell did contribute a few of its features to the POSIX standard, including:

  • $((...)) syntax for arithmetic expressions.

  • $(...) syntax for command substitution, except that the $(< filename ) shorthand for $(cat filename ) isn’t supported.

  • Tilde expansion (originally derived from the C shell).

The following Korn shell features are left “unspecified” in the standard, meaning that their syntax is acceptable but their functionality is not standardized:

  • The ((...)) syntax for arithmetic conditionals. The arithmetic test operators introduced in Chapter 5 (e.g., -eq, -lt), however, are included.

  • The [[...]] syntax for conditional tests. The external test or [...] utility should be used instead. The Korn shell’s version of test is POSIX-compliant when used with no more than three arguments. (It also complies with four arguments, if the first argument is !.)

  • The syntax for defining functions that this book uses. The other syntax shown in Chapter 4 (fname () instead of function fname) is supported, with what we described as “POSIX semantics;” see below.

  • The select control structure.

  • Signal numbers are only allowed if the numbers for certain key signals (INT, TERM, and a few others) are the same as on the most important historical versions of Unix. In general, shell scripts should use symbolic names for signals.

The POSIX standard supports functions, but the semantics are weaker than the Korn shell’s function-style functions: functions do not have local traps or options, and it is not possible to define local variables. (For this reason, ksh93 has two different syntaxes for defining functions, with different semantics.)

Code blocks ({...; }) are supported. For maximum portability, when you want literal curly braces, you should quote them (for reasons too complicated to go into here).

The POSIX standard introduced the following features, which are different from traditional Bourne shell behavior. ksh93 supports them all:

  • The command lookup order has been changed to allow certain built-in commands to be overridden by functions — since aliases aren’t included in the standard. Built-in commands are divided into two sets by their positions in the command lookup order: some are processed before functions, some after. Specifically, the built-in commands break, : (do nothing), continue, . (dot), eval, exec, exit, export, readonly, return, set, shift, trap, and unset take priority over functions.

  • A new built-in command, command, allows you to use built-in commands other than the above even if there are functions of the same name.[134]

  • A new keyword, !, takes the logical “not” of a command’s exit status: if command returns exit status 0, ! command returns 1; if command returns a non-zero value, ! command returns 0. ! can be used with &&, ||, and parentheses (for nested subshells) to create logical combinations of exit statuses in conditionals.

  • The command unset -v is used instead of unset (without an option) to remove the definition of a variable. This provides a better syntactic match with unset -f, for unsetting functions.

Finally, because the POSIX standard is meant to promote shell script portability, it explicitly avoids mention of features that only apply to interactive shell use — including aliases, editing modes, control keys, and so on. The User Portability Utilities option covers these. It also avoids mentioning certain key implementation issues: in particular, there is no requirement that multitasking be used for background jobs, subshells, etc. This was done to allow portability to non-multitasking systems like MS-DOS, so that, for example, the MKS Toolkit (see later in this appendix) can be POSIX compliant.

dtksh

The Desk Top Korn Shell (dtksh) is a standard part of the Common Desktop Environment (CDE), available on commercial Unix systems such as Solaris, HP-UX, and AIX. It is based on a somewhat older version of ksh93. It evolved from the earlier program wksh, the Windowing Korn shell, released by Unix System Laboratories in late 1992. It’s a full Korn shell, compatible with the version that this book describes,[135] that has extensions for graphical user interface (GUI) programming in the X Window System environment. It is typically found in /usr/dt/bin/dtksh.

dtksh supports the OSF/Motif graphical Toolkit by making its routines available as built-in commands. This allows programmers to combine the Korn shell’s strength as a Unix systems programming environment with the power and abstraction of the Toolkit. The result is a unified environment for quick and easy development of graphics-based software.

There are various GUI development tools that allow you to construct user interfaces with a graphics-based editor rather than with programming language code. But such tools are typically huge, expensive, and complex. dtksh, on the other hand, is inexpensive and unbeatable for the smoothness of its integration with Unix — it’s the only such tool that you can use as your login shell! (Well, almost; see the next section.) It is a definite option for systems programmers who use X-based workstations and need a rapid prototyping tool.

To give you the flavor of dtksh code, here is a script that implements the canonical “Hello World” program by displaying a small box with an “OK” button. It is from the article Graphical Desktop Korn Shell, in the July, 1998 issue of Linux Journal, by George Kraft IV. (See http://www.linuxjournal.com/article.php?sid=2643.) This code should hold no surprises for X and Motif programmers:

#!/usr/dt/bin/dtksh

XtInitialize TOPLEVEL dtHello DtHello "$@"

XmCreateMessageDialog HELLO $TOPLEVEL hello 
            dialogTitle:"DtHello" 
            messageString:"$(print "Hello
World")"
XmMessageBoxGetChild HELP $HELLO 
        DIALOG_HELP_BUTTON
XtUnmanageChild $HELP
XmMessageBoxGetChild CANCEL $HELLO 
        DIALOG_CANCEL_BUTTON
XtUnmanageChild $CANCEL
XtAddCallback $HELLO okCallback exit
XtManageChild $HELLO
XtMainLoop

http://www.cactus.org/~gk4/kraft/george/papers/dtksh/ is Mr. Kraft’s web presentation on dtksh.

The following book is devoted to dtksh: Desktop KornShell Graphical Programming by J. Stephen Pendergast, Jr., published by Addison-Wesley, 1995 (ISBN: 0-201-63375-2). Examples from the book are online at ftp://ftp.aw.com/aw.prof.comp.series/pendergrast.examples.tar.Z. Also available is ftp://ftp.aw.com/aw.prof.comp.series/pend.dtksh1, a text file that provides an overview of the book. Unfortunately, as of this writing, this book is out of print.

tksh

Back in 1996, while a computer science graduate student at Princeton University, Dr. Jeffrey L. Korn[136] wrote tksh. This is an integration of ksh93 with Tcl/Tk. The following quote (from Dr. Korn’s research web page) summarizes it well:

Tksh is a graphical language (similar to Visual Basic or Tcl/Tk) that uses KornShell (ksh93) for scripting and Tk for graphical user interface. Tksh is implemented as a ksh93 extension, and allows Tcl libraries such as Tk to run on top of ksh93 unchanged. ksh93 is well suited for graphical scripting because it is backward compatible with sh, making it both easy to learn and easy to extend existing scripts to provide user interface. Tksh also allows Tcl scripts to run without modification, making it possible to mix and match components written in either Tcl or ksh93.

The tksh home page is still at Princeton: http://www.cs.princeton.edu/~jlk/tksh/. It has links to papers and documentation that can be downloaded and printed. However, the link to tksh executables is out-of-date. The tksh source is available from AT&T Research as part of the ast-open package, which also contains ksh93 and reimplementations of many other Unix tools. See Appendix C for more information.

The following example script, from the USENIX paper on tksh, is called watchdir:

# Tksh Demo
# Jeff Korn
#
# This script keeps track of visited directories and shows the files
# in the current directory.   You can double-click on files and 
# directories.  The script should be used interactively, so to run:
#   $ tksh
#   $ . scripts/watchdir

function winsetup
{
    pack $(frame .f)
    frame .f.dirname -relief raised -bd 1
    pack .f.dirname -side top -fill x
    pack $(frame .f.ls) $(frame .f.dirs) -side left 
    label .f.dirname.label -text "Current directory: "
    label .f.dirname.pwd -textvariable PWD
    pack .f.dirname.label .f.dirname.pwd -side left

    scrollbar .f.ls.scroll -command ".f.ls.list yview"
    listbox .f.ls.list -yscroll ".f.ls.scroll set" -width 20 -setgrid 1
    pack $(label .f.ls.label -text "Directory Contents") -side top
    pack .f.ls.list .f.ls.scroll -side left -fill y -expand 1

    scrollbar .f.dirs.scroll -command ".f.dirs.list yview"
    listbox .f.dirs.list -yscroll ".f.dirs.scroll set" -width 20 -setgrid 1
    pack $(label .f.dirs.label -text "Visited Directories") -side top
    pack .f.dirs.list .f.dirs.scroll -side left -fill y -expand 1
    bind .f.dirs.list "<Double-1>" 'cd $(selection get)'
    bind .f.ls.list "<Double-1>" 'tkfileselect $(selection get)'
}

function tkfileselect
{
    [[ -d "$1" ]] && tkcd "$1"
    [[ -f "$1" ]] && ${EDITOR-${VISUAL-emacs}} "$1"
}

function tkcd
{
    cd $1 > /dev/null || return
    .f.ls.list delete 0 end
    set -o markdirs
    .f.ls.list insert end .. *
    [[ ${VisitedDir["$PWD"]} == "" ]] && .f.dirs.list insert end "$PWD"
    VisitedDir["$PWD"]=1
}

typeset -A VisitedDir
winsetup > /dev/null
alias cd=tkcd
tkcd .

What’s nice about tksh, besides the interesting blend of complementary technologies, is that it brings Tk programming out to the shell level. Graphics programming with Tk is much higher level than with the Motif toolkit; thus the learning curve is easier to climb, and the scripts are easier to read and write.

pdksh

Many of the Open Source Unix-like systems, such as GNU/Linux, come with the Public Domain Korn Shell, pdksh. pdksh is available as source code; start at its home page: http://www.cs.mun.ca/~michael/pdksh/. It comes with instructions for building and installing on various Unix platforms.

pdksh was originally written by Eric Gisin, who based it on Charles Forsyth’s public-domain clone of the Version 7 Bourne shell. It is mostly compatible with the 1988 Korn shell and POSIX, with some extensions of its own.

Its emacs editing mode is actually more powerful than that of the 1988 Korn shell. Like the full Emacs editor, you can customize the keystrokes that invoke editing commands (known as key bindings in Emacs terminology). Editing commands have full names that you can associate with keystrokes by using the bind command.

For example, if you want to set up CTRL-U to do the same thing as CTRL-P (i.e., go back to the previous command in the history file), you could put this command in your .profile:

bind '^U'=up-history

You can even set up two-character escape sequences, which (for example) allow you to use ANSI arrow keys as well as control characters, and you can define macros, i.e., abbreviations for sequences of editing commands.

The public domain Korn shell’s additional features include alternation wildcards (borrowed from the C shell) and user-definable tilde notation, in which you can set up ~ as an abbreviation for anything, not just user names. There are also a few subtle differences in integer expression evaluation and aliasing.

pdksh lacks the following features of the official version:

  • The built-in variable LINES.

  • The DEBUG fake signal. The fake signals ERR and EXIT within functions.

  • Functions inherit the trap settings of the main script.

  • The POSIX file expansion character classes ([[:alpha:]], etc.) are not available.

  • The read command and select loop do not use the command-line editing modes.

  • The last command of a pipeline is not run in the parent shell. Thus, echo hi | read x; print $x doesn’t work the same as in ksh. (Most Bourne-style shells work this same way.)

  • The set -o option form of ksh is set -X option in pdksh.

Although it lacks most ksh93 extensions, pdksh is a worthwhile alternative to the C and Bourne shells.

bash

bash is probably the most popular “third-party” shell that is available for Unix and other systems. In particular, it is the default shell on GNU/Linux systems. (It also comes on the “freeware” CD with Solaris 8.) You can get it from the Internet, via anonymous FTP to ftp.gnu.org in the directory /pub/gnu/bash. You can also order it from its maker at the address listed here.


The Free Software Foundation
59 Temple Place - Suite 330
Boston, MA  02111-1307
(617) 542-2652
(617) 542-5942 (fax)

            http://www.gnu.org
         

Bash was written by Brian Fox and Chet Ramey. Chet Ramey currently maintains it. Its name is in line with the FSF’s penchant for bad puns: it stands for Bourne-Again Shell. Although bash is easily available and you don’t have to pay for it (other than the cost of media, phone calls, etc.), it’s not really public domain software. While public domain software doesn’t have licensing restrictions, the FSF’s software does. But those restrictions are diametrically opposed to those in a commercial license:[137] instead of agreeing not to distribute the software further, you agree not to prevent it from being distributed further! In other words, you enjoy unrestricted use of the software as long as you agree not to inhibit others from doing the same. Richard Stallman, the founder of the FSF, invented this intriguing and admirable concept.

These days, the ideals of the Free Software and Open Source movements, the GNU project, and the quality of GNU software are all well known. The most popular GNU system is GNU/Linux, which uses the Linux kernel and GNU utilities to make a complete, fully functional, Unix- and POSIX-compatible computing environment.

bash is fully compatible with the 1992 POSIX standard. It has several of the most important Korn shell features and the C shell features that the Korn shell has appropriated, including aliases, functions, tilde notation, emacs and vi editing modes, arithmetic expressions, job control, etc.

The overlap of features between bash and the Korn shell has increased in recent years. It includes many ksh93 features. But it is not an exact ksh clone. The bash FAQ, published monthly by Chet Ramey, lists the following differences between bash and ksh93. Items enclosed in square brackets ([...]) are listed in this book, but not in the FAQ.

The following new things in ksh93 are not available in bash 2.05:

  • Associative arrays

  • Floating-point arithmetic and variables

  • Math library functions

  • ${!name[sub]} name of subscript for associative array

  • “.” is allowed in variable names to create a hierarchical namespace

  • More extensive compound assignment syntax

  • Discipline functions

  • sleep and getconf built-ins (bash has loadable versions)

  • typeset -n and nameref variables

  • The KEYBD trap

  • The variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version, .sh.name, .sh.subscript, .sh.value, HISTEDIT [The .sh.match variable also]

  • Backreferences in pattern matching (N)

  • The & operator in pattern lists for matching

  • print -f (bash uses printf)

  • fc has been renamed to hist

  • The dot command (.) can execute shell functions

  • Exit statuses between 0 and 255

  • The set -o pipefail option

  • The += variable assignment operator

  • TMOUT is default timeout for read and select

  • <& n - and >& n - redirections (combination dup and close) [Here-strings with <<<]

  • FPATH and PATH mixing

  • getopts -a

  • The -R invocation option

  • DEBUG trap now executed before each simple command, instead of after

  • The printf %H, %P, %T modifiers, and an output base for %d [Also %Z.]

The following new things in ksh93 are present in bash 2.05:

  • The for ((...;...;...)) ; do list; done arithmetic for command

  • The ?:, ++, --, and comma (,) arithmetic operators

  • The shell variable expansions: ${! param }, ${ param : offset[: len]}, ${ param / pat[/ str]}, ${! param *}

  • Compound array assignment

  • The ! reserved word

  • Loadable built-ins — but ksh uses builtin while bash uses enable

  • The command, builtin, and disown built-ins

  • New $'...' and $"..." quoting

  • FIGNORE (but bash uses GLOBIGNORE), HISTCMD

  • set -o notify, set -C

  • Changes to kill built-in

  • read -A (bash uses read -a)

  • read -t/read -d

  • trap -p

  • exec -a/exec -c

  • The dot command (.) restores the positional parameters when it completes

  • The test command conforms to POSIX.

  • umask -S

  • unalias -a

  • Command and arithmetic substitution performed on PS1, PS4, and ENV

  • Command name completion

  • ENV processed only for interactive shells

bash has many features of its own that make it a very powerful and flexible environment. Here are some of the highlights:

  • You can put backslash-escapes in the primary prompt string (PS1) for which bash substitutes things like the date, time, current working directory, machine name, user name, shell, etc.

  • The commands builtin, command, and enable give you more control over the steps bash goes through to look for commands — i.e., bash’s analogue to the list of command search steps in Chapter 7.

  • The emacs editing mode is customizable, even more so than its equivalent in pdksh. You can use the bind command to set up your own keystroke preferences, and there are several more commands available — including the ability to undo your last command.

  • You can also rebind keystrokes in vi editing mode.

  • pushd and popd are built-in, as they are in the C shell.

  • Indexed arrays may be of unlimited size.

  • Many new options and variables let you customize your environment with unprecedented flexibility. This includes set -o posix for strict POSIX conformance.

We’re compelled to say that many users prefer bash to the Korn shell. With the increasing popularity of GNU/Linux and various BSD-derived systems, it’s not clear which shell has the larger user base. In any case, bash is definitely an excellent choice. We recommend the book Learning the bash Shell by Cameron Newham and Bill Rosenblatt, published by O’Reilly & Associates. (It is based on the first edition of this book.)

zsh

zsh is a powerful interactive shell and scripting language with many features found in ksh, bash, and tcsh, as well as several unique features. zsh has most of the features of ksh88 but few of ksh93. It is freely available and should compile and run on just about any modern version of Unix. Ports for other operating systems are also available. The zsh home page is http://www.zsh.org. The current version is 4.0.2.

In this section we cover:

  • Extended globbing

  • Completion

  • Command-line editing

  • Prompts and prompt themes

  • Differences between zsh and ksh

Extended Globbing

A very useful feature is the recursive glob[138] operator, **. For example, a recursive grep is simple to construct:

grep foo **/*.c

Or to recursively find all files or directories named core, try:

print **/core

Another useful feature is glob qualifiers. There are many of these, for example, to print out only regular files in the current directory:

print *(.)

or just the directories:

print *(/)

Combining these with the recursive glob operator can be handy. We can improve the above example of finding core files by limiting the search to regular files only:

print **/core(.)

Another qualifier is U for file system objects you own. The following prints all files you own in /tmp and below:

print /tmp/**/*(U)

The glob qualifiers can also be combined. For example, using the socket file keyword = in combination with U, it’s easy to find socket files in /tmp and below that you own:

print /tmp/**/*(U=)

File size qualifiers are also available. For example, to find all files in your home directory that are greater than 10 megabytes in size:

print ~/**/*(Lm+10)

And file permission qualifiers are also available. For example, the W qualifier selects world-writable file system objects. You can use it to find all directories in your home directory and below that are owned by you and that are world-writeable:

print ~/**/*(UW/)

See zshexpn(1) for more information.

Completion

The zsh completion system is extremely sophisticated. The main idea is that any time you are about to type something on the command line, if you hit TAB, zsh will try to complete it. zsh comes with many defaults for completion and is also fully customizable.

To get a full set of default completion features, run the following commands (normally in your ~/.zshrc startup file):

autoload -U compinit
compinit

Now let’s look at some examples. We represent the TAB key in examples as [TAB].

First, zsh is smart about doing completions. For example, cd[TAB] only expands directories, thus eliminating completion noise.

Have you ever been frustrated because you can’t think of exactly the name of the command you want to find more information on, and man -k [139] hasn’t been configured on your system? Well, zsh will complete available man pages for you:

g@sifl:pts/7% man zsh[TAB]
zsh           zshcompctl    zshcontrib    zshmodules    zshzftpsys  
zshall        zshcompsys    zshexpn       zshoptions    zshzle      
zshbuiltins   zshcompwid    zshmisc       zshparam

Or maybe you want to find out a process name or PID you want to kill:

g@sifl:pts/2% kill [TAB]
 9652 pts/2    00:00:00 zsh                                                    
 9653 pts/2    00:00:00 ps

For finger, it expands users:

g@sifl:pts/7% finger o[TAB]
odin	omg	oof        operator	orb

and hosts:

g@sifl:pts/7% finger oof@[TAB]
brak	localhost 	sifl 	zorak

Using the distributed compdef function, you can define your own completions, using either your own custom functions or the completion functions that come with zsh. For example, the distribution defines the kill command to use the _pids distribution function to provide process identifiers. You can also use it to define completion for other commands, such as the Solaris pstack command:

compdef _pids pstack

Once this is done, you can apply completion to the pstack command like so:

g@sifl:pts/7% pstack [TAB]
13606 pts/7    00:00:00 zsh                                                    
13607 pts/7    00:00:00 ps

Another very useful distribution completion function is _gnu_generic. This can be applied to any command that uses the GNU --long-option command-line option conventions. The zsh distribution specifies many GNU commands to complete with this function (such as tar):

g@sifl:pts/7% tar --v[TAB]
--verbose      --verify       --version      --volno-file

And this is just the tip of the proverbial iceberg. There is much more to the zsh completion system; see zshcompsys(1) for the (gory) details.

Command-Line Editor

The zsh command-line editor is extremely powerful. It has several unique features, including multiline editing and an input buffer stack. The multiline command editor makes composing small scripts on the command line much easier then just having one line to edit with.

The input buffer stack comes in very handy. While you are typing a command, you can type ESC q, and the current line is pushed onto the buffer stack. The input line is then cleared, and you can type another command. When that has been executed, the previous line is popped off the stack and you can continue with that command. See zshzle(1) for more details.

Prompts and Prompt Themes

While most modern shells have customizable prompts, zsh raises it to an art form. One of the unique features is a right side prompt, RPROMPT, which is very useful for holding the current directory. This in turn removes clutter from the left hand prompt:

g@sifl:pts/2% RPROMPT='%~'
g@sifl:pts/2%                                    ~/src/xemacs-21.1.14

Also, you can define colors and bold fonts, and the prompt can be more than one line.

And as the notion of themes [140] has become popular in GUIs such as GNOME, zsh prompt themes can be defined; the distribution ships with several to choose from. To enable prompt themes, add these lines to your ~/.zshrc:

autoload -U promptinit
promptinit

To see what themes are available, run:

g@sifl:pts/2% prompt -l                                             ~
Currently available prompt themes:
adam1 adam2 bart bigfade clint elite2 elite fade fire off oliver
redhat suse zefram

To enable a theme, use the -s option. For example:

g@sifl:pts/7% prompt -s bart                                        ~
sifl [prompt -s bart] ~                              01-10-04 11:58PM
g@sifl:pts/7%                                                       ~

You can see that bart is a two-line prompt with several components such as the host name, the previous command, the current directory, and the date and time. See zshcontrib(1) for more details on prompt themes.

Differences Between zsh and ksh

This section is derived from information in the zsh FAQ.

Most features of ksh88 (and hence also of the Bourne shell, sh) are implemented in zsh; problems can arise because the implementation is slightly different. Note also that not all ksh’s are the same either. This is based on the 11/16/88f version of ksh; differences from ksh93 are more substantial.

As a summary of the status:

  1. Because of all the options, it is not safe to assume a general zsh run by a user will behave as if sh or ksh compatible.

  2. Invoking zsh as sh or ksh (or if either is a symbolic link to zsh) sets appropriate options and improves compatibility (from within zsh itself, calling ARGV0=sh zsh will also work).

  3. From Version 3.0 onward, the degree of compatibility with sh under these circumstances is very high: zsh can now be used with GNU configure or perl’s Configure, for example.

  4. The degree of compatibility with ksh is also high, but a few things are missing: for example, the more sophisticated pattern-matching expressions are different for versions before 3.1.3 — see the detailed list below.

  5. Also from 3.0, the command emulate is available: emulate ksh and emulate sh set various options as well as changing the effect of single-letter option flags, as if the shell had been invoked with the appropriate name. Including the command emulate sh; setopt localoptions in a shell function turns on sh emulation for that function only. In 4.0 (and in 3.0.6 through 8), this can be abbreviated as emulate -L sh.

The classic difference is word splitting: zsh keeps the result of plain $variable as one word, even if the variable contains white space. This trips up many beginning zsh users. The answer is to set SH_WORD_SPLIT for backward compatibility. The next most classic difference is that unmatched glob patterns cause the command to abort; set NO_NOMATCH for those.

zsh has a large set of options which increase ksh compatibility, though maybe decreasing zsh’s abilities: see the manual entries for the details. If invoked as ksh, the shell sets suitable options.

Here are some differences from ksh which might prove significant for ksh programmers, some of which may be interpreted as bugs. Note that this list is deliberately rather full and that most of the items are fairly minor. Those marked with † perform in a ksh-like manner if the shell is invoked with the name ksh or if emulate ksh is in effect. Capitalized words with underscores in their names refer to shell options.

Syntax
  • † Shell word splitting: see above.

  • † Arrays are (by default) more csh-like than ksh-like: subscripts start at 1, not 0; array[0] refers to array[1]; $array refers to the whole array, not $array[0]; braces are unnecessary: $a[1] is the same as ${a[1]}, etc. Set the KSH_ARRAYS option for compatibility.

  • Coprocesses are established by coproc; |& behaves like csh.[141] Handling of coprocess file descriptors is also different.

  • For cmd1 && cmd2 &, only cmd2, instead of the whole expression, is run in the background in zsh. The manual implies that this is a bug. Use { cmd1 && cmd2 } & as a workaround.

Command-line substitutions, globbing, etc.
  • † Failure to match a globbing pattern causes an error (use NO_NOMATCH).

  • † The results of parameter substitutions are treated as plain text: foo="*"; print $foo prints all files in ksh but prints * in zsh (use GLOB_SUBST).

  • † The prompt variables (e.g., PS1) do not undergo parameter substitution by default (use PROMPT_SUBST).

  • † Standard globbing does not allow ksh-style pattern-lists. Table A-1 shows equivalent patterns.

    The ^, ~ and # (but not |) forms require setting EXTENDED_GLOB. From version 3.1.3, the ksh forms are fully supported when the option KSH_GLOB is in effect; for previous versions you must use the equivalents given in Table A-1.

  • Unquoted assignments do file expansion after colons (intended for PATH-style variables).

  • integer does not allow -i.

  • typeset and integer have special behavior for assignments in ksh, but not in zsh. For example, this doesn’t work in zsh:

    integer k=$(wc -l ~/.zshrc)

    because the return value from wc includes leading whitespace, which causes wordsplitting. ksh handles the assignment specially, as a single word.

Table A-1. ksh/zsh pattern equivalents
kshzshMeaning
!(foo) ^foo

Anything but foo.

  foo1~foo2

Anything matching foo1 but not foo2.[a]

@(foo1|foo2|...) (foo1|foo2|...)

One of foo1 or foo2 or ...

?(foo) (foo|)

Zero or one occurrences of foo.

*(foo) (foo)#

Zero or more occurrences of foo.

+(foo) (foo)##

One or more occurrences of foo.

[a] Note that ~ is the only globbing operator to have a lower precedence than /. For example, **/foo~*bar* matches any file in a subdirectory called foo, except where bar occurred somewhere in the path (e.g. users/barstaff/foo will be excluded by the ~ operator). As the ** operator cannot be grouped (inside parentheses it is treated as *), this is the way to exclude some subdirectories from matching a **.

Command execution
  • † There is no ENV variable (use /etc/zshrc, ~/.zshrc; note also $ZDOTDIR).

  • $PATH is not searched for commands specified at invocation without -c.

Aliases and functions
  • The order in which aliases and functions are defined is significant: function definitions with () expand aliases.

  • Aliases and functions cannot be exported.

  • There are no tracked aliases: command hashing replaces these.

  • The use of aliases for key bindings is replaced by bindkey.

  • † Options are not local to functions (use LOCAL_OPTIONS; note this may always be unset locally to propagate options settings from a function to the calling level).

  • Functions defined with function funcname { body ;} behave the same way as those defined with funcname () { body ;}. In ksh93, only the former behave as true functions, and the latter behave as if the body were read from a file with the dot command.

Traps and signals
  • † Traps are not local to functions. The option LOCAL_TRAPS is available from 3.1.6.

  • TRAPERR has become TRAPZERR (this was forced by UNICOS which has SIGERR).

Editing
  • The options emacs, gmacs, and viraw are not supported. Use bindkey to change the editing behavior: set -o emacs becomes bindkey -e and set -o vi becomes bindkey -v; for gmacs, go to emacs-mode and use bindkey ^t gosmacs-transpose-characters.

  • The keyword option does not exist and set -k is instead interactivecomments.

  • † Management of histories in multiple shells is different: the history list is not saved and restored after each command. The option SHARE_HISTORY appeared in 3.1.6 and is set in ksh compatibility mode to remedy this.

  • does not escape editing chars (use CTRL-V).

  • Not all ksh bindings are set (e.g. ESC #; try ESC q).

  • # in an interactive shell is not treated as a comment by default.

Built-in commands
  • Some built-ins (r, autoload, history, integer, ...) are aliases in ksh.

  • There is no built-in command newgrp: use alias newgrp="exec newgrp".

  • jobs has no -n flag.

  • read has no -s flag.

Other idiosyncrasies
  • select always redisplays the list of selections on each loop.

Workalikes on PC Platforms

The proliferation of the Korn shell has not stopped at the boundaries of Unix-dom. Many programmers who got their initial experience on Unix systems and subsequently crossed over into the PC world wished for a nice Unix-like environment (especially when faced with the horrors of the MS-DOS command line!), so it’s not surprising that several Unix shell-style interfaces to small-computer operating systems have appeared, Korn shell emulations among them.

In the past several years, not just shell clones have appeared, but entire Unix “environments.” Two of them use shells that we’ve already discussed. Two others provide their own shell reimplementations. Providing lists of major and minor differences is counterproductive. Instead, this section describes each environment in turn (in alphabetical order), along with contact and Internet download information.

Cygwin

Cygnus Consulting (now Red Hat), created the cygwin environment. First creating cgywin.dll, a shared library that provides Unix system call emulation, they ported a large number of GNU utilities to various versions of Microsoft Windows. The emulation includes TCP/IP networking with the Berkeley socket API. The greatest functionality comes under Windows/NT, Windows 2000, and Windows XP, although the environment can and does work under Windows 95/98/ME, as well.

The cygwin environment uses bash for its shell, GCC for its C compiler, and the rest of the GNU utilities for its Unix toolset. A sophisticated mount command provides a mapping of the Windows C:path notation to Unix filenames.

The starting point for the cygwin project is http://www.cygwin.com. The first thing to download is an installer program. Upon running it, you choose what additional packages you wish to install. Installation is entirely Internet-based; there are no official cygwin CD’s, at least not from the project maintainers.

DJGPP

The DJGPP suite provides 32-bit GNU tools for the MS-DOS environment. To quote the web page:

DJGPP is a complete 32-bit C/C++ development system for Intel 80386 (and higher) PCs running MS-DOS. It includes ports of many GNU development utilities. The development tools require a 80386 or newer computer to run, as do the programs they produce. In most cases, the programs it produces can be sold commercially without license or royalties.

The name comes from the initials of D.J. Delorie, who ported the GNU C++ compiler, g++ to MS-DOS, and the text initials of g++, GPP. It grew into essentially a full Unix environment on top of MS-DOS, with all the GNU tools and bash as its shell. Unlike cygwin or UWIN (see later in this chapter), you don’t need a version of Windows, just a full 32-bit processor and MS-DOS. (Although, of course, you can use DJGPP from within a Windows MS-DOS window.) The web site is http://www.delorie.com/djgpp/.

MKS Toolkit

Perhaps the most established Unix environment for the PC world is the MKS Toolkit from Mortice Kern Systems:

MKS Canada - Corporate Headquarters
410 Albert Street
Waterloo, ON N2L 3V3
Canada
(519) 884-2251
(519) 884-8861 (fax)
(800) 265-2797 (sales)
http://www.mks.com

The MKS Toolkit comes in various versions depending upon the development environment and the number of developers who will be using it. It includes a shell that is POSIX compliant, along with just about all the features of the 1988 Korn shell, as well as over 300 utilities, such as awk, perl, vi, make, and so on. Their library supports over 1500 Unix APIs, making it extremely complete and easing porting to the Windows environment. More information is available at http://www.mkssoftware.com/products/tk/ds_tkpdev.asp.

Thompson Automation Software Toolkit

Thompson Automation Software provides the Thompson Toolkit, which includes a shell and over 100 utilities. The toolkit is available MS-DOS 2.1 and higher, OS/2 1.2 or WARP, and for Microsoft Windows 95 and higher. The contact information is:


Thompson Automation Software
5616 SW Jefferson
Portland, OR 97221
1-800-944-0139 (U.S. and Canada)
1-503-224-1639 (international/local)
1-503-224-3230 (FAX)

               http://www.tasoft.com/toolkit.html/
            

Thompson software is best known for their implementation of awk, which is both fast and reliable, with many powerful extensions to the awk language. The toolkit shell is compatible with POSIX and the 1988 version of the Korn shell.

AT&T UWIN

The UWIN package is a project by David Korn and his colleagues to make a Unix environment available under Microsoft Windows. It is similar in structure to cygwin, discussed earlier. A shared library, posix.dll, provides emulation of the Unix system call APIs. The system call emulation is quite complete. An interesting twist is that the Windows registry can be accessed as a filesystem under /reg. On top of the Unix API emulation, ksh93 and over 200 Unix utilities (or rather, reimplementations) have been compiled and run. The UWIN environment relies on the native Microsoft Visual C/C++ compiler, although the GNU development tools are available for download and use with UWIN.

http://www.research.att.com/sw/tools/uwin/ is the web page for the project. It describes what is available, with links for downloading binaries, as well as information on commercial licensing of the UWIN package. Also included are links to various papers on UWIN, additional useful software, and links to other, similar packages.

The most notable advantage to the UWIN package is that its shell is the authentic ksh93. Thus, compatibility with the Unix version of ksh93 isn’t an issue.



[131] There are also a few differences in how the two shells react to certain extremely pathological input. Usually, the Korn shell processes correctly what causes the Bourne shell to “choke.”

[132] In the original Version 7 Bourne Shell (and in Berkeley Unix systems through 4.3BSD), test and [ condition ] were actually external commands. (They were hard links to each other in /bin.) However, they’ve been built into the Bourne shell in all systems since System III (circa 1981).

[133] The <> operator was in the original Version 7 Bourne shell, but not documented, since it didn’t always work correctly across all Unix systems. Its availability should not be relied upon for Bourne shell programming.

[134] But note that it’s not a special built-in! Design by committee shows through here.

[135] Features listed throughout the book as being introduced for “recent” versions won’t be in dtksh.

[136] Yes, David Korn’s son. He now works in the same research center as his father at AT&T Laboratories, although in a different area.

[137] Accordingly, the document that spells out these restrictions is called a copyleft.

[138] Globbing is technical slang for wildcard expansion.

[139] This does a keyword search of an online database extracted from the man pages.

[140] Some popular GUIs, such as GNOME, support themes. Rather than having one immutable look and feel, they can be changed to different styles, or themes. The distributions of these GUIs often contain several to choose from. Some of these tend to emulate other GUI’s, while others are new and are mostly fun window dressing.

[141] In csh, |& sends both standard output and standard error down the same pipeline; it is equivalent to ... 2>&1 | ....

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.197.183