home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume35
/
zsh
/
part03
< prev
next >
Wrap
Text File
|
1993-02-20
|
57KB
|
2,439 lines
Newsgroups: comp.sources.misc
From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Subject: v35i053: zsh - The Z Shell, version 2.3.1, Part03/22
Message-ID: <1993Feb20.212032.28166@sparky.imd.sterling.com>
X-Md4-Signature: cbf11e1334e0785c3220a1644257cb50
Date: Sat, 20 Feb 1993 21:20:32 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Posting-number: Volume 35, Issue 53
Archive-name: zsh/part03
Environment: UNIX
Supersedes: zsh2.2: Volume 29, Issue 97-113
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: doc/intro.txt.01 help/autoload src/Makefile.sample
# Wrapped by mattson@odin on Sat Feb 6 14:41:51 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 3 (of 22)."'
if test -f 'doc/intro.txt.01' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/intro.txt.01'\"
else
echo shar: Extracting \"'doc/intro.txt.01'\" \(49646 characters\)
sed "s/^X//" >'doc/intro.txt.01' <<'END_OF_FILE'
X
X
X
X
X
X
X An Introduction to the Z Shell
X
X
X Paul Falstad
X pf@ttisms.com
X
X
X
X
X
X
Xzsh is a shell designed for interactive use, although it is
Xalso a powerful scripting language. Many of the useful
Xfeatures of bash, ksh, and tcsh were incorporated into zsh;
Xmany original features were added. This document details
Xsome of the unique features of zsh. It assumes basic
Xknowledge of the standard UNIX shells; the intent is to show
Xa reader already familiar with one of the other major shells
Xwhat makes zsh more useful or more powerful. This document
Xis not at all comprehensive; read the manual entry for a
Xdescription of the shell that is complete and concise,
Xalthough somewhat overwhelming and devoid of examples.
X
XFilename Generation
X
XOtherwise known as globbing, filename generation is quite
Xextensive in zsh. Of course, it has all the basics:
X
X% ls
XMakefile file.pro foo.o main.o q.c run234 stuff
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
X% ls *.c
Xfoo.c q.c
X% ls *.[co]
Xbar.o foo.c foo.o main.o q.c
X% ls foo.?
Xfoo.c foo.o
X% ls *.[^c]
Xbar.o file.h foo.o main.h main.o
X% ls *.[^oh]
Xfoo.c q.c
X
X
XAlso, if the EXTENDEDGLOB option is set, some new features
Xare activated. For example, the ^ character negates the
Xpattern following it:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 2 -
X
X% setopt extendedglob
X% ls -d ^*.c
XMakefile file.pro link morestuff run2 run303
Xbar.o foo main.h pipe run234 stuff
Xfile.h foo.o main.o run123 run240 sub
X% ls -d ^*.*
XMakefile link pipe run2 run240 stuff
Xfoo morestuff run123 run234 run303 sub
X% ls -d ^Makefile
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff
X% ls -d *.^c
X.rhosts bar.o file.h file.pro foo.o main.h main.o
X
X
XAn expression of the form <x-y> matches a range of integers:
X
X% ls run<200-300>
Xrun234 run240
X% ls run<300-400>
Xrun303
X% ls run<-200>
Xrun123 run2
X% ls run<300->
Xrun303
X% ls run<>
Xrun123 run2 run234 run240 run303
X
X
XGrouping is possible:
X
X% ls (foo|bar).*
Xbar.o foo.c foo.o
X% ls *.(c|o|pro)
Xbar.o file.pro foo.c foo.o main.o q.c
X
X
XAlso, the string **/ forces a recursive search of sub-
Xdirectories:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 3 -
X
X% ls -R
XMakefile file.pro foo.o main.o q.c run234 stuff
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
X
Xmorestuff:
X
Xstuff:
Xfile xxx yyy
X
Xstuff/xxx:
Xfoobar
X
Xstuff/yyy:
Xfrobar
X% ls **/*bar
Xstuff/xxx/foobar stuff/yyy/frobar
X% ls **/f*
Xfile.h foo foo.o stuff/xxx/foobar
Xfile.pro foo.c stuff/file stuff/yyy/frobar
X% ls *bar*
Xbar.o
X% ls **/*bar*
Xbar.o stuff/xxx/foobar stuff/yyy/frobar
X% ls stuff/**/*bar*
Xstuff/xxx/foobar stuff/yyy/frobar
X
X
X
XIt is possible to exclude certain files from the patterns
Xusing the ~ character. A pattern of the form *.c~bar.c
Xlists all files matching *.c, except for the file bar.c.
X
X% ls *.c
Xfoo.c foob.c bar.c
X% ls *.c~bar.c
Xfoo.c foob.c
X% ls *.c~f*
Xbar.c
X
X
X
XOne can add a number of qualifiers to the end of any of
Xthese patterns, to restrict matches to certain file types.
XA qualified pattern is of the form
X
X pattern(...)
X
X
Xwith single-letter qualifiers inside the parentheses.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 4 -
X
X% alias l='ls -dF'
X% l *
XMakefile foo* main.h q.c run240
Xbar.o foo.c main.o run123 run303
Xfile.h foo.o morestuff/ run2 stuff/
Xfile.pro link@ pipe run234 sub
X% l *(/)
Xmorestuff/ stuff/
X% l *(@)
Xlink@
X% l *(*)
Xfoo* link@ morestuff/ stuff/
X% l *(x)
Xfoo* link@ morestuff/ stuff/
X% l *(X)
Xfoo* link@ morestuff/ stuff/
X% l *(R)
Xbar.o foo* link@ morestuff/ run123 run240
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff/
X
X
XNote that *(x) and *(*) both match executables. *(X)
Xmatches files executable by others, as opposed to *(x),
Xwhich matches files executable by the owner. *(R) and *(r)
Xmatch readable files; *(W) and *(w), which checks for writ-
Xable files. *(W) is especially important, since it checks
Xfor world-writable files:
X
X% l *(w)
Xbar.o foo* link@ morestuff/ run123 run240
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff/
X% l *(W)
Xlink@ run240
X% l -l link run240
Xlrwxrwxrwx 1 pfalstad 10 May 23 18:12 link -> /bin/false*
X-rw-rw-rw- 1 pfalstad 0 May 23 18:12 run240
X
X
XYou can filter out the symbolic links with the ^ character:
X
X% l *(W^@)
Xrun240
X% l *(x)
Xfoo* link@ morestuff/ stuff/
X% l *(x^@/)
Xfoo*
X
X
XTo find all plain files, you can use .:
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 5 -
X
X% l *(.)
XMakefile file.h foo* foo.o main.o run123 run234 run303
Xbar.o file.pro foo.c main.h q.c run2 run240 sub
X% l *(^.)
Xlink@ morestuff/ pipe stuff/
X% l s*(.)
Xstuff/ sub
X% l *(p)
Xpipe
X% l -l *(p)
Xprw-r--r-- 1 pfalstad 0 May 23 18:12 pipe
X
X
X*(U) matches all files owned by you. To search for all
Xfiles not owned by you, use *(^U):
X
X% l -l *(^U)
X-rw------- 1 subbarao 29 May 23 18:13 sub
X
X
XThis searches for setuid files:
X
X% l -l *(s)
X-rwsr-xr-x 1 pfalstad 16 May 23 18:12 foo*
X
X
XThis checks for a certain user's files:
X
X% ypmatch subbarao passwd
Xsubbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh
X% l -l *(u3338)
X-rw------- 1 subbarao 29 May 23 18:13 sub
X
X
X
XStartup Files
X
XThere are five startup files that zsh will read commands
Xfrom:
X
X$ZDOTDIR/.zshenv
X$ZDOTDIR/.zprofile
X$ZDOTDIR/.zshrc
X$ZDOTDIR/.zlogin
X$ZDOTDIR/.zlogout
X
X
XIf ZDOTDIR is not set, then the value of HOME is used; this
Xis the usual case.
X
X.zshenv is sourced on all invocations of the shell, unless
Xthe -f option is set. It should contain commands to set the
Xcommand search path, plus other important environment vari-
Xables. .zshenv should not contain commands that produce
Xoutput or assume the shell is attached to a tty.
X
X.zshrc is sourced in interactive shells. It should contain
Xcommands to set up aliases, functions, options, key bind-
Xings, etc.
X
X
X
X
X
X - 6 -
X.zlogin is sourced in login shells. It should contain com-
Xmands that should be executed only in login shells. .zlo-
Xgout is sourced when login shells exit. .zprofile is simi-
Xlar to .zlogin, except that it is sourced before .zshrc.
X.zprofile is meant as an alternative to .zlogin for ksh
Xfans; the two are not intended to be used together, although
Xthis could certainly be done if desired. .zlogin is not the
Xplace for alias definitions, options, environment variable
Xsettings, etc.; as a general rule, it should not change the
Xshell environment at all. Rather, it should be used to set
Xthe terminal type and run a series of external commands
X(fortune, msgs, etc).
X
XShell Functions
X
Xzsh also allows you to create your own commands by defining
Xshell functions. For example:
X
X% yp () {
X> ypmatch $1 passwd.byname
X> }
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XThis function looks up a user in the NIS password map. The
X$1 expands to the first argument to yp. The function could
Xhave been equivalently defined in one of the following ways:
X
X% function yp {
X> ypmatch $1 passwd.byname
X> }
X% function yp () {
X> ypmatch $1 passwd.byname
X> }
X% function yp () ypmatch $1 passwd.byname
X
X
XNote that aliases are expanded when the function definition
Xis parsed, not when the function is executed. For example:
X
X% alias ypmatch=echo
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XSince the alias was defined after the function was parsed,
Xit has no effect on the function's execution. However, if
Xwe define the function again with the alias in place:
X
X% function yp () { ypmatch $1 passwd.byname }
X% yp pfalstad
Xpfalstad passwd.byname
X
X
Xit is parsed with the new alias definition in place. There-
Xfore, in general you must define aliases before functions.
X
XWe can make the function take multiple arguments:
X
X
X
X
X
X
X - 7 -
X
X% unalias ypmatch
X% yp () {
X> for i
X> do ypmatch $i passwd.byname
X> done
X> }
X% yp pfalstad subbarao sukthnkr
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
Xsubbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
XThe for i loops through each of the function's arguments,
Xsetting i equal to each of them in turn. We can also make
Xthe function do something sensible if no arguments are
Xgiven:
X
X% yp () {
X> if (( $# == 0 ))
X> then echo usage: yp name ...; fi
X> for i; do ypmatch $i passwd.byname; done
X> }
X% yp
Xusage: yp name ...
X% yp pfalstad sukthnkr
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
X$# is the number of arguments supplied to the function. If
Xit is equal to zero, we print a usage message; otherwise, we
Xloop through the arguments, and ypmatch all of them.
X
XHere's a function that selects a random line from a file:
X
X% randline () {
X> integer z=$(wc -l <$1)
X> sed -n $[RANDOM % z + 1]p $1
X> }
X% randline /etc/motd
XPHOENIX WILL BE DOWN briefly Friday morning, 5/24/91 from 8 AM to
X% randline /etc/motd
XSunOS Release 4.1.1 (PHOENIX) #19: Tue May 14 19:03:15 EDT 1991
X% randline /etc/motd
X| Please use the "msgs" command to read announcements. Refer to the |
X% echo $z
X
X%
X
X
Xrandline has a local variable, z, that holds the number of
Xlines in the file. $[RANDOM % z + 1] expands to a random
Xnumber between 1 and z. An expression of the form $[...]
Xexpands to the value of the arithmetic expression within the
Xbrackets, and the RANDOM variable returns a random number
Xeach time it is referenced. % is the modulus operator, as
Xin C. Therefore, sed -n $[RANDOM%z+1]p picks a random line
Xfrom its input, from 1 to z.
X
X
X
X
X
X
X - 8 -
XFunction definitions can be viewed with the functions buil-
Xtin:
X
X% functions randline
Xrandline () {
X integer z=$(wc -l <$1)
X sed -n $[RANDOM % z + 1]p $1
X
X}
X% functions
Xyp () {
X if let $# == 0
X
X then
X echo usage: yp name ...
X
X fi
X for i
X do
X ypmatch $i passwd.byname
X
X done
X
X}
Xrandline () {
X integer z=$(wc -l <$1)
X sed -n $[RANDOM % z + 1]p $1
X
X}
X
X
XHere's another one:
X
X% cx () { chmod +x $* }
X% ls -l foo bar
X-rw-r--r-- 1 pfalstad 29 May 24 04:38 bar
X-rw-r--r-- 1 pfalstad 29 May 24 04:38 foo
X% cx foo bar
X% ls -l foo bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo
X
X
XNote that this could also have been implemented as an alias:
X
X% chmod 644 foo bar
X% alias cx='chmod +x'
X% cx foo bar
X% ls -l foo bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo
X
X
X
XInstead of defining a lot of functions in your .zshrc, all
Xof which you may not use, it is often better to use the
Xautoload builtin. The idea is, you create a directory where
Xfunction definitions are stored, declare the names in your
X.zshrc, and tell the shell where to look for them. Whenever
Xyou reference a function, the shell will automatically load
X
X
X
X
X
X - 9 -
Xit into memory.
X
X% mkdir /tmp/funs
X% cat >/tmp/funs/yp
Xypmatch $1 passwd.byname
X^D
X% cat >/tmp/funs/cx
Xchmod +x $*
X^D
X% FPATH=/tmp/funs
X% autoload cx yp
X% functions cx yp
Xundefined cx ()
Xundefined yp ()
X% chmod 755 /tmp/funs/{cx,yp}
X% yp egsirer
Xegsirer:*:3214:35:Emin Gun Sirer:/u/egsirer:/bin/sh
X% functions yp
Xyp () {
X ypmatch $1 passwd.byname
X}
X
X
XThis idea has other benefits. By adding a #! header to the
Xfiles, you can make them double as shell scripts. (Although
Xit is faster to use them as functions, since a separate pro-
Xcess is not created.)
X
X% ed /tmp/funs/yp
X25
Xi
X#! /usr/local/bin/zsh
Xw
X42
Xq
X% </tmp/funs/yp
X#! /usr/local/bin/zsh
Xypmatch $1 passwd.byname
X% /tmp/funs/yp sukthnkr
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
XNow other people, who may not use zsh, or who don't want to
Xcopy all of your .zshrc, may use these functions as shell
Xscripts.
X
XDirectories
X
XOne nice feature of zsh is the way it prints directories.
XFor example, if we set the prompt like this:
X
Xphoenix% PROMPT='%~> '
X~> cd src
X~/src>
X
X
Xthe shell will print the current directory in the prompt,
Xusing the ~ character. However, zsh is smarter than most
Xother shells in this respect:
X
X
X
X
X
X
X - 10 -
X
X~/src> cd ~subbarao
X~subbarao> cd ~maruchck
X~maruchck> cd lib
X~maruchck/lib> cd fun
X~maruchck/lib/fun> foo=/usr/princeton/common/src
X~maruchck/lib/fun> cd ~foo
X~foo> cd ..
X/usr/princeton/common> cd src
X~foo> cd news/nntp
X~foo/news/nntp> cd inews
X~foo/news/nntp/inews>
X
X
XNote that zsh prints other users' directories in the form
X~user. Also note that you can set a parameter and use it as
Xa directory name; zsh will act as if foo is a user with the
Xlogin directory /usr/princeton/common/src. This is con-
Xvenient, especially if you're sick of seeing prompts like
Xthis:
X
Xphoenix:/usr/princeton/common/src/X.V11R4/contrib/clients/xv/docs>
X
X
XIf you get stuck in this position, you can give the current
Xdirectory a short name, like this:
X
X/usr/princeton/common/src/news/nntp/inews> inews=$PWD
X/usr/princeton/common/src/news/nntp/inews> echo ~inews
X/usr/princeton/common/src/news/nntp/inews
X~inews>
X
X
XWhen you reference a directory in the form ~inews, the shell
Xassumes that you want the directory displayed in this form;
Xthus simply typing echo ~inews or cd ~inews causes the
Xprompt to be shortened. You can define a shell function for
Xthis purpose:
X
X~inews> namedir () { $1=$PWD ; : ~$1 }
X~inews> cd /usr/princeton/bin
X/usr/princeton/bin> namedir pbin
X~pbin> cd /var/spool/mail
X/var/spool/mail> namedir spool
X~spool> cd .msgs
X~spool/.msgs>
X
X
XYou may want to add this one-line function to your .zshrc.
X
Xzsh can also put the current directory in your title bar, if
Xyou are using a windowing system. One way to do this is
Xwith the chpwd function, which is automatically executed by
Xthe shell whenever you change directory. If you are using
Xxterm, this will work:
X
Xchpwd () { print -Pn '^[]2;%~^G' }
X
X
XThe -P option tells print to treat its arguments like a
X
X
X
X
X
X - 11 -
Xprompt string; otherwise the %~ would not be expanded. The
X-n option suppresses the terminating newline, as with echo.
X
XIf you are using an IRIS wsh, do this:
X
Xchpwd () { print -Pn '^[P1.y%~^[' }
X
X
XThe print -D command has other uses. For example, to print
Xthe current directory to standard output in short form, you
Xcan do this:
X
X% print -D $PWD
X~subbarao/src
X
X
Xand to print each component of the path in short form:
X
X% print -D $path
X/bin /usr/bin ~locbin ~locbin/X11 ~/bin
X
X
X
XDirectory Stacks
X
XIf you use csh, you may know about directory stacks. The
Xpushd command puts the current directory on the stack, and
Xchanges to a new directory; the popd command pops a direc-
Xtory off the stack and changes to it.
X
Xphoenix% cd
Xphoenix% PROMPT='Z %~> '
XZ ~> pushd /tmp
X/tmp ~
XZ /tmp> pushd /usr/etc
X/usr/etc /tmp ~
XZ /usr/etc> pushd /usr/bin
X/usr/bin /usr/etc /tmp ~
XZ /usr/bin> popd
X/usr/etc /tmp ~
XZ /usr/etc> popd
X/tmp ~
XZ /tmp> pushd /etc
X/etc /tmp ~
XZ /etc> popd
X/tmp ~
X
X
Xzsh's directory stack commands work similarly. One differ-
Xence is the way pushd is handled if no arguments are given.
XAs in csh, this exchanges the top two elements of the direc-
Xtory stack:
X
XZ /tmp> dirs
X/tmp ~
XZ /tmp> pushd
X~ /tmp
X
X
Xunless the stack only has one entry:
X
X
X
X
X
X - 12 -
X
XZ ~> popd
X/tmp
XZ /tmp> dirs
X/tmp
XZ /tmp> pushd
X~ /tmp
X
X
Xor unless the PUSHDTOHOME option is set:
X
XZ ~> setopt pushdtohome
XZ ~> pushd
X~ ~ /tmp
X
X
X
XAs an alternative to using directory stacks in this manner,
Xwe can get something like a directory history by setting a
Xfew more options and parameters:
X
X~> DIRSTACKSIZE=8
X~> setopt autopushd pushdminus pushdsilent pushdtohome
X~> alias dh='dirs -v'
X~> cd /tmp
X/tmp> cd /usr
X/usr> cd bin
X/usr/bin> cd ../pub
X/usr/pub> dh
X0 /usr/pub
X1 /usr/bin
X2 /usr
X3 /tmp
X4 ~
X/usr/pub> cd -3
X/tmp> dh
X0 /tmp
X1 /usr/pub
X2 /usr/bin
X3 /usr
X4 ~
X/tmp> ls =2/df
X/usr/bin/df
X/tmp> cd -4
X~>
X
X
XNote that =2 expanded to the second directory in the history
Xlist, and that cd -3 recalled the third directory in the
Xlist.
X
XYou may be wondering what all those options do. AUTOPUSHD
Xmade cd act like pushd. (alias cd=pushd is not sufficient,
Xfor various reasons.) PUSHDMINUS swapped the meaning of cd
X+1 and cd -1; we want them to mean the opposite of what they
Xmean in csh, because it makes more sense in this scheme, and
Xit's easier to type:
X
X
X
X
X
X
X
X
X - 13 -
X
X~> dh
X0 ~
X1 /tmp
X2 /usr/pub
X3 /usr/bin
X4 /usr
X~> unsetopt pushdminus
X~> cd +1
X/tmp> dh
X0 /tmp
X1 ~
X2 /usr/pub
X3 /usr/bin
X4 /usr
X/tmp> cd +2
X/usr/pub>
X
X
XPUSHDSILENT keeps the shell from printing the directory
Xstack each time we do a cd, and PUSHDTOHOME we mentioned
Xearlier:
X
X/usr/pub> unsetopt pushdsilent
X/usr/pub> cd /etc
X/etc /usr/pub /tmp ~ /usr/bin /usr
X/etc> cd
X~ /etc /usr/pub /tmp ~ /usr/bin /usr
X~> unsetopt pushdtohome
X~> cd
X/etc ~ /usr/pub /tmp ~ /usr/bin /usr
X/etc>
X
X
XDIRSTACKSIZE keeps the directory stack from getting too
Xlarge, much like HISTSIZE:
X
X/etc> setopt pushdsilent
X/etc> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> dh
X0 /
X1 /
X2 /
X3 /
X4 /
X5 /
X6 /
X7 /
X
X
X
X
X
X
X
X
X
X
X - 14 -
XCommand/Process Substitution
X
XCommand substitution in zsh can take two forms. In the
Xtraditional form, a command enclosed in backquotes (`...`)
Xis replaced on the command line with its output. This is
Xthe form used by the older shells. Newer shells (like zsh)
Xalso provide another form, $(...). This form is much easier
Xto nest.
X
X% ls -l `echo /vmunix`
X-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix
X% ls -l $(echo /vmunix)
X-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix
X% who | grep mad
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xpfalstad ttyu1 May 23 16:25 (mad55sx14.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xpfalstad ttyv3 May 23 16:25 (mad55sx14.Prince)
X% who | grep mad | awk '{print $2}'
Xttyt7
Xttyu1
Xttyu6
Xttyv3
X% cd /dev; ls -l $(who |
X> grep $(echo mad) |
X> awk '{ print $2 }')
Xcrwx-w---- 1 subbarao 20, 71 May 23 18:35 ttyt7
Xcrw--w---- 1 pfalstad 20, 81 May 23 18:42 ttyu1
Xcrwx-w---- 1 subbarao 20, 86 May 23 18:38 ttyu6
Xcrw--w---- 1 pfalstad 20, 99 May 23 18:41 ttyv3
X
X
XMany common uses of command substitution, however, are
Xsuperseded by other mechanisms of zsh:
X
X% ls -l `tty`
Xcrw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc
X% ls -l $TTY
Xcrw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc
X% ls -l `which rn`
X-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn
X% ls -l =rn
X-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn
X
X
XA command name with a = prepended is replaced with its full
Xpathname. This can be very convenient. If it's not con-
Xvenient for you, you can turn it off:
X
X% ls
X=foo =bar
X% ls =foo =bar
Xzsh: foo not found
X% setopt noequals
X% ls =foo =bar
X=foo =bar
X
X
X
XAnother nice feature is process substitution:
X
X
X
X
X
X - 15 -
X
X% who | fgrep -f =(print -l root lemke shgchan subbarao)
Xroot console May 19 10:41
Xlemke ttyq0 May 22 10:05 (narnia:0.0)
Xlemke ttyr7 May 22 10:05 (narnia:0.0)
Xlemke ttyrd May 22 10:05 (narnia:0.0)
Xshgchan ttys1 May 23 16:52 (gaudi.Princeton.)
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xshgchan ttyvb May 23 16:51 (gaudi.Princeton.)
X
X
XA command of the form =(...) is replaced with the name of a
Xfile containing its output. (A command substitution, on the
Xother hand, is replaced with the output itself.) print -l is
Xlike echo, excepts that it prints its arguments one per
Xline, the way fgrep expects them:
X
X% print -l foo bar
Xfoo
Xbar
X
X
XWe could also have written:
X
X% who | fgrep -f =(echo 'root
X> lemke
X> shgchan
X> subbarao')
X
X
XUsing process substitution, you can edit the output of a
Xcommand:
X
X% ed =(who | fgrep -f ~/.friends)
X355
Xg/lemke/d
Xw /tmp/filbar
X226
Xq
X% cat /tmp/filbar
Xroot console May 19 10:41
Xshgchan ttys1 May 23 16:52 (gaudi.Princeton.)
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xshgchan ttyvb May 23 16:51 (gaudi.Princeton.)
X
X
Xor easily read archived mail:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 16 -
X
X% mail -f =(zcat ~/mail/oldzshmail.Z)
X"/tmp/zsha06024": 84 messages, 0 new, 43 unread
X> 1 U TO: pfalstad, zsh (10)
X 2 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3
X 3 U JAM%TPN@utrcgw.utc.com, zsh fix (15)
X 4 U djm@eng.umd.edu, way to find out if running zsh? (25)
X 5 U djm@eng.umd.edu, Re: way to find out if running zsh? (17)
X 6 r djm@eng.umd.edu, Meta . (18)
X 7 U jack@cs.glasgow.ac.uk, Re: problem building zsh (147)
X 8 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3
X 9 ursa!jmd, Another fix... (61)
X 10 U pplacewa@bbn.com, Re: v18i084: Zsh 2.00 - A small complaint (36)
X 11 U lubkin@cs.rochester.edu, POSIX job control (34)
X 12 U yale!bronson!tan@uunet.UU.NET
X 13 U brett@rpi.edu, zsh (36)
X 14 S subbarao, zsh sucks!!!! (286)
X 15 U snibru!d241s008!d241s013!ala@relay.EU.net, zsh (165)
X 16 U nytim!tim@uunet.UU.NET, Re: Zsh on Sparc1 /SunOS 4.0.3
X 17 U subbarao, zsh is a junk shell (43)
X 18 U amaranth@vela.acs.oakland.edu, zsh (33)
X43u/84 1: x
X% ls -l /tmp/zsha06024
X/tmp/zsha06024 not found
X
X
XNote that the shell creates a temporary file, and deletes it
Xwhen the command is finished.
X
X% diff =(ls) =(ls -F)
X3c3
X< fortune
X---
X> fortune*
X10c10
X< strfile
X---
X> strfile*
X
X
XIf you read zsh's man page, you may notice that <(...) is
Xanother form of process substitution which is similar to
X=(...). There is an important difference between the two.
XIn the <(...) case, the shell creates a named pipe (FIFO)
Xinstead of a file. This is better, since it does not fill
Xup the file system; but it does not work in all cases. In
Xfact, if we had replaced =(...) with <(...) in the examples
Xabove, all of them would have stopped working except for
Xfgrep -f <(...). You can not edit a pipe, or open it as a
Xmail folder; fgrep, however, has no problem with reading a
Xlist of words from a pipe. You may wonder why diff <(foo)
Xbar doesn't work, since foo | diff - bar works; this is
Xbecause diff creates a temporary file if it notices that one
Xof its arguments is -, and then copies its standard input to
Xthe temporary file.
X
XAliasing
X
XOften-used commands can be abbreviated with an alias:
X
X
X
X
X
X
X - 17 -
X
X% alias uc=uncompress
X% ls
Xhanoi.Z
X% uc hanoi
X% ls
Xhanoi
X
X
Xor commands with certain desired options:
X
X% alias fm='finger -m'
X% fm root
XLogin name: root In real life: Operator
XDirectory: / Shell: /bin/csh
XOn since May 19 10:41:15 on console 3 days 5 hours Idle Time
XNo unread mail
XNo Plan.
X
X% alias lock='lock -p -60000'
X% lock
Xlock: /dev/ttyr4 on phoenix. timeout in 60000 minutes
Xtime now is Fri May 24 04:23:18 EDT 1991
XKey:
X
X% alias l='ls -AF'
X% l /
X.bash_history kadb*
X.bashrc lib@
X.cshrc licensed/
X.exrc lost+found/
X.login macsyma
X
X
XAliases can also be used to replace old commands:
X
X% alias grep=egrep ps=sps make=gmake
X% alias whoami='echo root'
X% whoami
Xroot
X
X
Xor to define new ones:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 18 -
X
X% cd /
X% alias sz='ls -l | sort -n +3 | tail -10'
X% sz
Xdrwxr-sr-x 7 bin 3072 May 23 11:59 etc
Xdrwxrwxrwx 26 root 5120 May 24 04:20 tmp
Xdrwxr-xr-x 2 root 8192 Dec 26 19:34 lost+found
Xdrwxr-sr-x 2 bin 14848 May 23 18:48 dev
X-r--r--r-- 1 root 140520 Dec 26 20:08 boot
X-rwxr-xr-x 1 root 311172 Dec 26 20:08 kadb
X-rwxr-xr-x 1 root 1209695 Apr 16 15:33 vmunix.old
X-rwxr-xr-x 1 root 1209702 May 14 19:04 vmunix
X-rwxr-xr-x 1 root 1209758 May 21 12:23 vmunix.new.kernelmap.old
X-rwxr-xr-x 1 root 1711848 Dec 26 20:08 vmunix.org
X% cd
X% alias rable='ls -AFtrd *(R)' nrable='ls -AFtrd *(^R)'
X% rable
XREADME func/ bin/ pub/ News/ src/
Xnicecolors etc/ scr/ tmp/ iris/ zsh*
X% nrable
XMailboxes/ mail/ notes
X
X
X(The pattern *(R) matches all readable files in the current
Xdirectory, and *(^R) matches all unreadable files.)
X
XMost other shells have aliases of this kind (command
Xaliases). However, zsh also has global aliases, which are
Xsubstituted anywhere on a line. Global aliases can be used
Xto abbreviate frequently-typed usernames, hostnames, etc.
X
X% alias -g me=pfalstad gun=egsirer mjm=maruchck
X% who | grep me
Xpfalstad ttyp0 May 24 03:39 (mickey.Princeton)
Xpfalstad ttyp5 May 24 03:42 (mickey.Princeton)
X% fm gun
XLogin name: egsirer In real life: Emin Gun Sirer
XDirectory: /u/egsirer Shell: /bin/sh
XLast login Thu May 23 19:05 on ttyq3 from bow.Princeton.ED
XNew mail received Fri May 24 02:30:28 1991;
X unread since Fri May 24 02:30:27 1991
X% alias -g phx=phoenix.princeton.edu warc=wuarchive.wustl.edu
X% ftp warc
XConnected to wuarchive.wustl.edu.
X
X
XHere are some more interesting uses.
X
X% alias -g M='| more' GF='| fgrep -f ~/.friends'
X% who M # pipes the output of who through more
X% who GF # see if your friends are on
X% w GF # see what your friends are doing
X
X
XAnother example makes use of zsh's process substitution. If
Xyou run NIS, and you miss being able to do this:
X
X% grep pfalstad /etc/passwd
X
X
X
X
X
X
X
X - 19 -
Xyou can define an alias that will seem more natural than
Xypmatch pfalstad passwd:
X
X% alias -g PASS='<(ypcat passwd)'
X% grep pfalstad PASS
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XIf you're really crazy, you can even call it /etc/passwd:
X
X% alias -g /etc/passwd='<(ypcat passwd)'
X% grep pfalstad /etc/passwd
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XThe last example shows one of the perils of global aliases;
Xthey have a lot of potential to cause confusion. For exam-
Xple, if you defined a global alias called | (which is possi-
Xble), zsh would begin to act very strangely; every pipe sym-
Xbol would be replaced with the text of your alias. To some
Xextent, global aliases are like macros in C; discretion is
Xadvised in using them and in choosing names for them. Using
Xnames in all caps is not a bad idea, especially for aliases
Xwhich introduce shell metasyntax (like M and GF above).
X
XNote that zsh aliases are not like csh aliases. The syntax
Xfor defining them is different, and they do not have argu-
Xments. All your favorite csh aliases will probably not work
Xunder zsh. For example, if you try:
X
Xalias rm mv '\!* /tmp/wastebasket'
X
X
Xno aliases will be defined, but zsh will not report an
Xerror. In csh, this line defines an alias that makes rm
Xsafe---files that are rm'd will be moved to a temporary
Xdirectory instead of instantly destroyed. In zsh's syntax,
Xhowever, this line asks the shell to print any existing
Xalias definitions for rm, mv, or !* /tmp/wastebasket. Since
Xthere are none, most likely, the shell will not print any-
Xthing, although alias will return a nonzero exit code. The
Xproper syntax is this:
X
Xalias rm='mv \!* /tmp/wastebasket'
X
X
XHowever, this won't work either:
X
X% rm foo.dvi
Xzsh: no matches found: !*
X
X
XWhile this makes rm safe, it is certainly not what the user
Xintended. In zsh, you must use a shell function for this:
X
X% unalias rm
X% rm () { mv $* /tmp/wastebasket }
X% rm foo.dvi
X% ls /tmp/wastebasket
Xfoo.dvi
X
X
X
X
X
X - 20 -
XWhile this is much cleaner and easier to read (I hope you
Xwill agree), it is not csh-compatible. Therefore, a script
Xto convert csh aliases and variables has been provided. You
Xshould only need to use it once, to convert all your csh
Xaliases and parameters to zsh format:
X
X% csh
Xcsh> alias
Xl ls -AF
Xmore less
Xon last -2 !:1 ; who | grep !:1
Xcsh> exit
X% c2z >neat_zsh_aliases
X% cat neat_zsh_aliases
Xalias l='ls -AF'
Xalias more='less'
Xon () { last -2 $1 ; who | grep $1 }
X...
X
X
XThe first two aliases were converted to regular zsh aliases,
Xwhile the third, since it needed to handle arguments, was
Xconverted to a function. c2z can convert most aliases to
Xzsh format without any problems. However, if you're using
Xsome really arcane csh tricks, or if you have an alias with
Xa name like do (which is reserved in zsh), you may have to
Xfix some of the aliases by hand.
X
XThe c2z script checks your csh setup, and produces a list of
Xzsh commands which replicate your aliases and parameter set-
Xtings as closely as possible. You could include its output
Xin your startup file, .zshrc.
X
XHistory
X
XThere are several ways to manipulate history in zsh. One
Xway is to use csh-style ! history:
X
X% /usr/local/bin/!:0 !-2*:s/foo/bar/ >>!$
X
X
XIf you don't want to use this, you can turn it off by typing
Xsetopt nobanghist.
X
XAnother way is to use the fc command. For example, if you
Xtype an erroneous command:
X
X% for i in `cat /etc/clients`
X do
X rpu $i
X done
Xzsh: command not found: rpu
Xzsh: command not found: rpu
Xzsh: command not found: rpu
X
X
Xtyping fc will execute an editor on this command, allowing
Xyou to fix it. (The default editor is vi, by the way, not
Xed).
X
X
X
X
X
X
X - 21 -
X
X% fc
X49
X/rpu/s//rup/p
X rup $i
Xw
X49
Xq
Xfor i in `cat /etc/clients`
X do
X rup $i
X done
X beam up 2 days, 10:17, load average: 0.86, 0.80, 0.50
X bow up 4 days, 8:41, load average: 0.91, 0.80, 0.50
X burn up 17:18, load average: 0.91, 0.80, 0.50
X burst up 9 days, 1:49, load average: 0.95, 0.80, 0.50
X tan up 11:14, load average: 0.91, 0.80, 0.50
X bathe up 3 days, 17:49, load average: 1.84, 1.79, 1.50
X bird up 1 day, 9:13, load average: 1.95, 1.82, 1.51
X bonnet up 2 days, 21:18, load average: 0.93, 0.80, 0.50
X
X
XA variant of the fc command is r, which redoes the last com-
Xmand, with optional changes:
X
X% echo foo
Xfoo
X% r
Xecho foo
Xfoo
X
X% echo foo
Xfoo
X% r foo=bar
Xecho bar
Xbar
X
X
X
XCommand Line Editing
X
Xzsh's command line editor, ZLE, is quite powerful. It is
Xdesigned to emulate either emacs or vi; the default is
Xemacs. To set the bindings for vi mode, type bindkey -v.
X
XIn addition to basic editing, the shell allows you to recall
Xprevious lines in the history. In emacs mode, this is done
Xwith ^P (control-P):
X
X% ls ~
X- README file mail pub tmp
XMailboxes bin func nicecolors scr zsh
XNews etc iris notes src
X% echo foobar
Xfoobar
X% ^P
X% echo foobar^P
X% ls ~_
X
X
X
X
X
X
X
X - 22 -
XPressing ^P once brings up the previous line (echo foobar);
Xpressing it again brings up the line before that (ls ~).
XThe cursor is left at the end of the line, allowing you to
Xedit the line if desired before executing it. In many
Xcases, ZLE eliminates the need for the fc command, since it
Xis powerful enough to handle even multiline commands:
X
X% for i in a b c d e
X> do
X> echo $i
X> done
Xa
Xb
Xc
Xd
Xe
X% ^P
X% for i in a b c d e
X do
X echo $i
X done_
X
X
XNow you can just move up to the part you want to change...
X
X% for i in _ b c d e
X do
X echo $i
X done
X
X
Xchange it, and execute the new command.
X
X% for i in f g h i j
X do
X echo $i
X done
Xf
Xg
Xh
Xi
Xj
X
X
XAlso, you can search the history for a certain command using
XESC-P:
X
X% set ESC-P
X% setopt autolist ESC-P
X% setopt nocorrect_
X
X
XAnother way is to do an incremental search, emacs-style:
X
X
X
X
X
X
X
X
X
X
X
X
X - 23 -
X
X% ^R
X% _
Xi-search:
X
X% l_ /usr/bin
Xi-search: l
X
X% date > foofile_c
Xi-search: le
X
X
XAnother useful feature of the editor is command and filename
Xcompletion.
X
X% compTAB
X% compress _
X
X% ls /nicTAB
X% ls /nicecolors _
X
X% ls /usr/prTAB
X% ls /usr/princeton/_
X
X% ls -l =comTAB
X% ls -l =compress _
X
X
XIf the completion is ambiguous, the editor will beep. You
Xcan list possible completions by pressing ^D:
X
X% ls /vmuTAB -beep-
X% ls /vmunix_
X% ls /vmunix^D
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X
X
XOr, you could just set the AUTOLIST option:
X
X% setopt autolist
X% ls /vmuTAB -beep-
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_
X
X
XAnother option you could set is RECEXACT, which causes exact
Xmatches to be accepted, even if there are other possible
Xcompletions:
X
X% setopt recexact
X% ls /vmuTAB -beep-
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_TAB
X% ls /vmunix _
X
X
XThe fignore variable lists suffixes of files to ignore
X
X
X
X
X
X - 24 -
Xduring completion.
X
X% ls fooTAB -beep-
Xfoofile.c foofile.o
X% fignore=( .o \~ .bak .junk )
X% ls fooTAB
X% ls foofile.c _
X
X
XSince foofile.o has a suffix that is in the fignore list, it
Xwas not considered a possible completion of foo.
X
XUsername completion is also supported:
X
X% ls ~pfalTAB
X% ls ~pfalstad/_
X
X
Xand parameter name completion:
X
X% echo $ORGTAB
X% echo $ORGANIZATION _
X
X
Xand hostname completion, if you give the shell a list of
Xhosts to complete:
X
X% hosts=( phoenix.princeton.edu uunet.uu.net nic.ddn.mil
X> diskfarm.princeton.edu gnu.ai.mit.edu
X> eniac.seas.upenn.edu )
X% telnet diskTAB
X% telnet diskfarm.princeton.edu _
X
X% ftp uuTAB
X% ftp uunet.uu.net _
X
X% mail subbarao@phTAB
X% mail subbarao@phoenix.princeton.edu _
X
X
Xand option completion:
X
X% setopt noclTAB
X% setopt noclobber _
X
X
Xand binding completion:
X
X% bindkey '^X^X' puTAB
X% bindkey '^X^X' push-line _
X
X
X
XThe compctl command is used to control how completion works.
XFor example, to specify that certain commands show take com-
Xmands as arguments, you use compctl -c:
X
X% compctl -c man nohup
X% man uptTAB
X% man uptime _
X
X
X
X
X
X - 25 -
XTo specify that a command should complete filenames, you
Xshould use compctl -f. This is the default. It can be com-
Xbined with -c, as well.
X
X% compctl -cf echo
X% echo uptTAB
X% echo uptime _
X
X% echo foTAB
X% echo foo.c
X
X
XSimilarly, use -h to specify hostnames, -o to specify
Xoptions, -v to specify variables, and -b to specify bind-
Xings.
X
X% compctl -h rlogin
X% compctl -hfc rsh
X% compctl -b bindkey
X
X
XYou can also use -k to specify a custom list of keywords to
Xuse in completion.
X
X% ftphosts=(ftp.uu.net wuarchive.wustl.edu)
X% compctl -k ftphosts ftp
X% ftp wuTAB
X% ftp wuarchive.wustl.edu _
X
X% friends=(cpirazzi subbarao sukthnkr)
X% compctl -k friends mail finger su
X% finger cpTAB
X% finger cpirazzi _
X
X
X
XIn addition to completion, TAB performs expansion if possi-
Xble.
X
X% ls *.cTAB
X% ls foofile.c fortune.c rnd.c strfile.c unstr.c_
X
X
XFor example, suppose you have a bunch of weird files in an
Ximportant directory:
X
X% ls
X * * * ; & % $??foo dspfok foo.c
X !"foo"! ` \ ` foo rrr
X
X
XYou want to remove them, but you don't want to damage foo.c.
XHere is one way to do this:
X
X% rm *TAB
X% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$'
X'foo \`\ \\\ \` dspfok foo foo.c rrr_
X
X
XWhen you expand *, zsh inserts the names of all the files
X
X
X
X
X
X - 26 -
Xinto the editing buffer, with proper shell quoting. Now,
Xjust move back and remove foo.c from the buffer:
X
X% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$'
X'foo \`\ \\\ \` dspfok foo _rr
X
X
Xand press return. Everything except foo.c will be deleted
Xfrom the directory.
X
XHere's another trick; let's say you have typed this command
Xin:
X
X% gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs_
X
X
Xand you forget which library you want. You need to escape
Xout for a minute and check by typing ls /usr/lib, or some
Xother such command; but you don't want to retype the whole
Xcommand again, and you can't press return now because the
Xcurrent command is incomplete. In zsh, you can put the line
Xon the buffer stack, using ESC-Q, and type some other com-
Xmands. The next time a prompt is printed, the gcc line will
Xbe popped off the stack and put in the editing buffer
Xautomatically; you can then enter the proper library name
Xand press return (or, ESC-Q again and look for some other
Xlibraries whose names you forgot).
X
XA similar situation: what if you forget the option to gcc
Xthat finds bugs using AI techniques? You could either use
XESC-Q again, and type man gcc, or you could press ESC-H,
Xwhich essentially does the same thing; it puts the current
Xline on the buffer stack, and executes the command run-help
Xgcc, where run-help is an alias for man.
X
XAnother interesting command is ESC-A. This executes the
Xcurrent line, but retains it in the buffer, so that it
Xappears again when the next prompt is printed. Also, the
Xcursor stays in the same place. This is useful for execut-
Xing a series of similar commands:
X
X% cc grok.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X% cc fubar.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X% cc fooble.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X
X
X
XThe ESC-' command is useful for managing the shell's quoting
Xconventions. Let's say you want to print this string:
X
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
XAll that is necessary is to type it into the editing buffer:
X
X% don't do that; type 'rm -rf \*', with a \ before the *.
X
X
Xpress ESC-' (escape-quote):
X
X
X
X
X
X
X - 27 -
X
X% 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.'
X
X
Xthen move to the beginning and add the echo command.
X
X% echo 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.'
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
XLet's say you want to create an alias to do this echo com-
Xmand. This can be done by recalling the line with ^P and
Xpressing ESC-' again:
X
X% 'echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm -rf
X\*'\''\'\'''\'', with a \ before the *.'\'''
X
X
Xand then move to the beginning and add the command to create
Xan alias.
X
X% alias zoof='echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm
X-rf \*'\''\'\'''\'', with a \ before the *.'\'''
X% zoof
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
X
XAnother interesting option is MENUCOMPLETE. This affects
Xthe way TAB works. Let's look at the /vmunix example again:
X
X% setopt menucomplete
X% ls /vmuTAB
X% ls /vmunixTAB
X% ls /vmunix.new.kernelmap.oldTAB
X% ls /vmunix.old_
X
X
XEach time you press TAB, it displays the next possible com-
Xpletion. In this way, you can cycle through the possible
Xcompletions until you find the one you want.
X
XThe AUTOMENU option makes a nice compromise between this
Xmethod of completion and the regular method. If you set
Xthis option, pressing the TAB key repeatedly after an ambi-
Xguous completion will cycle through the possible comple-
Xtions.
X
XBindings
X
XEach of the above editor commands was actually a function
Xbound by default to a certain key. The real names of the
Xcommands are:
X
Xexpand-or-complete TAB
Xpush-line ESC-Q
Xrun-help ESC-H
Xaccept-and-hold ESC-A
Xquote-line ESC-'
X
X
X
X
X
X
X - 28 -
XThese bindings are arbitrary; you could change them if you
Xwant. For example, to bind accept-line to ^Z:
X
X% bindkey '^Z' accept-line
X
X
XAnother idea would be to bind the delete key to delete-char;
Xthis might be convenient if you use ^H for backspace.
X
X% bindkey '^?' delete-char
X
X
XOr, you could bind ^X^H to run-help:
X
X% bindkey '^X^H' run-help
X
X
XOther examples:
X
X% bindkey '^X^Z' universal-argument
X% bindkey ' ' magic-space
X% bindkey -s '^T' 'uptime
X> '
X
X
Xuniversal-argument multiplies the next command by 4. Thus
X^X^Z^W might delete the last four words on the line. If you
Xbind space to magic-space, then csh-style history expansion
Xis done on the line whenever you press the space bar.
X
XThe -s flag to bindkey specifies that you are binding the
Xkey to a string, not a command. Thus bindkey -s '^T'
X'uptime\n' lets you VMS lovers get the load average whenever
Xyou press ^T.
X
XIf you have a NeXT keyboard, the one with the | and \ keys
Xvery inconveniently placed, the following bindings may come
Xin handy:
X
X% bindkey -s '\e/' '\\'
X% bindkey -s '\e=' '|'
X
X
XNow you can type ALT-/ to get a backslash, and ALT-= to get
Xa vertical bar. This only works inside zsh, of course;
Xbindkey has no effect on the key mappings inside talk or
Xmail, etc.
X
XAnother use of the editor is to edit the value of variables.
XFor example, an easy way to change your path is to use the
Xvared command:
X
X% vared PATH
X> /u/pfalstad/scr:/u/pfalstad/bin/sun4:/u/maruchck/scr:/u/subbarao/bin:/u/maruc
Xhck/bin:/u/subbarao/scripts:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/usr/host
Xs:/usr/princeton/bin/X11:/./usr/lang:/./usr/etc:/./etc
X
X
XYou can now edit the path. When you press return, the con-
Xtents of the edit buffer will be assigned to PATH.
X
X
X
X
X
X - 29 -
XParameter Substitution
X
XIn zsh, parameters are set like this:
X
X% foo=bar
X% echo $foo
Xbar
X
X
XSpaces before or after the = are frowned upon:
X
X% foo = bar
Xzsh: command not found: foo
X
X
XAlso, set doesn't work for setting parameters:
X
X% set foo=bar
X% set foo = bar
X% echo $foo
X
X%
X
X
XNote that no error message was printed. This is because
Xboth of these commands were perfectly valid; the set builtin
Xassigns its arguments to the positional parameters ($1, $2,
Xetc.).
X
X% set foo=bar
X% echo $1
Xfoo=bar
X% set foo = bar
X% echo $3 $2
Xbar =
X
X
XIf you're really intent on using the csh syntax, define a
Xfunction like this:
X
X% set () {
X> eval "$1$2$3"
X> }
X% set foo = bar
X% set fuu=brrr
X% echo $foo $fuu
Xbar brrr
X
X
XBut then, of course you can't use the form of set with
Xoptions, like set -F (which turns off filename generation).
XAlso, the set command by itself won't list all the parame-
Xters like it should. To get around that you need a case
Xstatement:
X
X
X
X
X
X
X
X
X
X
X
X - 30 -
X
X% set () {
X> case $1 in
X> -*|+*|'') builtin set $* ;;
X> *) eval "$1$2$3" ;;
X> esac
X> }
X
X
XFor the most part, this should make csh users happy.
X
XThe following sh-style operators are supported in zsh:
X
X% unset null
X% echo ${foo-xxx}
Xbar
X% echo ${null-xxx}
Xxxx
X% unset null
X% echo ${null=xxx}
Xxxx
X% echo $null
Xxxx
X% echo ${foo=xxx}
Xbar
X% echo $foo
Xbar
X% unset null
X% echo ${null+set}
X
X% echo ${foo+set}
Xset
X
X
XAlso, csh-style : modifiers may be appended to a parameter
Xsubstitution.
X
X% echo $PWD
X/home/learning/pf/zsh/zsh2.00/src
X% echo $PWD:h
X/home/learning/pf/zsh/zsh2.00
X% echo $PWD:h:h
X/home/learning/pf/zsh
X% echo $PWD:t
Xsrc
X% name=foo.c
X% echo $name
Xfoo.c
X% echo $name:r
Xfoo
X% echo $name:e
Xc
X
X
XThe equivalent constructs in ksh (which are also supported
Xin zsh) are a bit more general and easier to remember. When
Xthe shell expands ${foo#pat}, it checks to see if pat
Xmatches a substring at the beginning of the value of foo.
XIf so, it removes that portion of foo, using the shortest
Xpossible match. With ${foo##pat}, the longest possible
X
X
X
X
X
X - 31 -
Xmatch is removed. ${foo%pat} and ${foo%%pat} remove the
Xmatch from the end. Here are the ksh equivalents of the :
Xmodifiers:
X
X% echo ${PWD%/*}
X/home/learning/pf/zsh/zsh2.00
X% echo ${PWD%/*/*}
X/home/learning/pf/zsh
X% echo ${PWD##*/}
Xsrc
X% echo ${name%.*}
Xfoo
X% echo ${name#*.}
Xc
X
X
Xzsh also has upper/lowercase modifiers:
X
X% xx=Test
X% echo $xx:u
XTEST
X% echo $xx:l
Xtest
X
X
Xand a substitution modifier:
X
X% echo $name:s/foo/bar/
Xbar.c
X% ls
Xfoo.c foo.h foo.o foo.pro
X% for i in foo.*; mv $i $i:s/foo/bar/
X% ls
Xbar.c bar.h bar.o bar.pro
X
X
XOne possible source of confusion is the fact that in zsh,
Xthe result of parameter substitution is not split into
Xwords. Thus, this will not work:
X
X% srcs='glob.c exec.c init.c'
X% ls $srcs
Xglob.c exec.c init.c not found
X
X
XThis is considered a feature, not a bug. If splitting were
Xdone by default, as it is in most other shells, functions
Xlike this would not work properly:
X
X$ ll () { ls -F $* }
X$ ll 'fuu bar'
Xfuu not found
Xbar not found
X
X% ll 'fuu bar'
Xfuu bar not found
X
X
XOf course, a hackish workaround is available in sh (and
Xzsh):
X
X
X
X
X
X - 32 -
X
X% setopt shwordsplit
X% ll () { ls -F "$@" }
X% ll 'fuu bar'
Xfuu bar not found
X
X
XIf you like the sh behaviour, zsh can accomodate you:
X
X% ls ${=srcs}
Xexec.c glob.c init.c
X% setopt shwordsplit
X% ls $srcs
Xexec.c glob.c init.c
X
X
XAnother way to get the $srcs trick to work is to use an
Xarray:
X
X% unset srcs
X% srcs=( glob.c exec.c init.c )
X% ls $srcs
Xexec.c glob.c init.c
X
X
Xor an alias:
X
X% alias -g SRCS='exec.c glob.c init.c'
X% ls SRCS
Xexec.c glob.c init.c
X
X
XAnother option that modifies parameter expansion is RCEX-
XPANDPARAM:
X
X% echo foo/$srcs
Xfoo/glob.c exec.c init.c
X% setopt rcexpandparam
X% echo foo/$srcs
Xfoo/glob.c foo/exec.c foo/init.c
X% echo foo/${^srcs}
Xfoo/glob.c foo/exec.c foo/init.c
X% echo foo/$^srcs
Xfoo/glob.c foo/exec.c foo/init.c
X
X
X
XShell Parameters
X
XThe shell has many predefined parameters that may be
Xaccessed. Here are some examples:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 33 -
X
X% sleep 10 &
X[1] 3820
X% echo $!
X3820
X% set a b c
X% echo $#
X3
X% echo $ARGC
X3
X% ( exit 20 ) ; echo $?
X20
X% false; echo $status
X1
X
X
X($? and $status are equivalent.)
X
X% echo $HOST $HOSTTYPE
Xdendrite sun4
X% echo $UID $GID
X701 60
X% cd /tmp
X% cd /home
X% echo $PWD $OLDPWD
X/home /tmp
X% ls $OLDPWD/.getwd
X/tmp/.getwd
X
X
X~+ and ~- are short for $PWD and $OLDPWD, respectively.
X
X% ls ~-/.getwd
X/tmp/.getwd
X% ls -d ~+/learning
X/home/learning
X% echo $RANDOM
X4880
X% echo $RANDOM
X11785
X% echo $RANDOM
X2062
X% echo $TTY
X/dev/ttyp4
X% echo $VERSION
Xzsh v2.00.03
X% echo $USERNAME
Xpf
X
X
X
XThe cdpath variable sets the search path for the cd command.
XIf you do not specify . somewhere in the path, it is assumed
Xto be the first component.
X
X
X
X
X
X
X
X
X
X
X
X - 34 -
X
X% cdpath=( /usr ~ ~/zsh )
X% ls /usr
X5bin dict lang net sccs sys
X5include etc lector nserve services tmp
X5lib export lib oed share ucb
Xadm games local old skel ucbinclude
Xbin geac lost+found openwin spool ucblib
Xboot hosts macsyma_417 pat src xpg2bin
Xdemo include man princeton stand xpg2include
Xdiag kvm mdec pub swap xpg2lib
X% cd spool
X/usr/spool
X% cd bin
X/usr/bin
X% cd func
X~/func
X% cd
X% cd pub
X% pwd
X/u/pfalstad/pub
X% ls -d /usr/pub
X/usr/pub
X
X
XPATH and path both set the search path for commands. These
Xtwo variables are equivalent, except that one is a string
Xand one is an array. If the user modifies PATH, the shell
Xchanges path as well, and vice versa.
X
X% PATH=/bin:/usr/bin:/tmp:.
X% echo $path
X/bin /usr/bin /tmp .
X% path=( /usr/bin . /usr/local/bin /usr/ucb )
X% echo $PATH
X/usr/bin:.:/usr/local/bin:/usr/ucb
X
X
XThe same is true of CDPATH and cdpath:
X
X% echo $CDPATH
X/usr:/u/pfalstad:/u/pfalstad/zsh
X% CDPATH=/u/subbarao:/usr/src:/tmp
X% echo $cdpath
X/u/subbarao /usr/src /tmp
X
X
XIn general, parameters with names in all lowercase are
Xarrays; assignments to them take the form:
X
Xname=( elem ... )
X
X
XParameters with names in all uppercase are strings. If
Xthere is both an array and a string version of the same
Xparameter, the string version is a colon-separated list,
Xlike PATH.
X
XHISTFILE is the name of the history file, where the history
Xis saved when a shell exits.
X
X
X
X
X
X - 35 -
X
X% zsh
Xphoenix% HISTFILE=/tmp/history
Xphoenix% SAVEHIST=20
Xphoenix% echo foo
Xfoo
Xphoenix% date
XFri May 24 05:39:35 EDT 1991
Xphoenix% uptime
X 5:39am up 4 days, 20:02, 40 users, load average: 2.30, 2.20, 2.00
Xphoenix% exit
X% cat /tmp/history
XHISTFILE=/tmp/history
XSAVEHIST=20
Xecho foo
Xdate
Xuptime
Xexit
X% HISTSIZE=3
X% history
X 28 rm /tmp/history
X 29 HISTSIZE=3
X 30 history
X
X
X
XIn zsh, if you say
X
X% >file
X
X
Xthe command cat is normally assumed:
X
X% >file
Xfoo!
X^D
X% cat file
Xfoo!
X
X
END_OF_FILE
if test 49646 -ne `wc -c <'doc/intro.txt.01'`; then
echo shar: \"'doc/intro.txt.01'\" unpacked with wrong size!
fi
# end of 'doc/intro.txt.01'
fi
if test -f 'help/autoload' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'help/autoload'\"
else
echo shar: Extracting \"'help/autoload'\" \(274 characters\)
sed "s/^X//" >'help/autoload' <<'END_OF_FILE'
X autoload [ name ... ]
X For each of the names (which are names of functions),
X create a function marked undefined. The fpath variable
X will be searched to find the actual function definition
X when the function is first referenced.
END_OF_FILE
if test 274 -ne `wc -c <'help/autoload'`; then
echo shar: \"'help/autoload'\" unpacked with wrong size!
fi
# end of 'help/autoload'
fi
if test -f 'src/Makefile.sample' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/Makefile.sample'\"
else
echo shar: Extracting \"'src/Makefile.sample'\" \(1851 characters\)
sed "s/^X//" >'src/Makefile.sample' <<'END_OF_FILE'
X#! /bin/make -f
X# Makefile for zsh
X# generated by buildzsh
X
XAUX=buildzsh
X
XSRC=builtin.c cond.c exec.c glob.c hist.c init.c jobs.c lex.c loop.c \
Xmath.c mem.c params.c parse.c subst.c table.c text.c utils.c watch.c \
Xzle_bindings.c zle_hist.c zle_main.c zle_misc.c zle_move.c zle_refresh.c \
Xzle_tricky.c zle_utils.c zle_vi.c zle_word.c
X
XHEADER=funcs.h zle.h zsh.h ztype.h
X
XPROTO=builtin.pro cond.pro exec.pro glob.pro hist.pro init.pro jobs.pro \
Xlex.pro loop.pro math.pro mem.pro params.pro parse.pro subst.pro table.pro \
Xtext.pro utils.pro watch.pro zle_bindings.pro zle_hist.pro zle_main.pro \
Xzle_misc.pro zle_move.pro zle_refresh.pro zle_tricky.pro zle_utils.pro \
Xzle_vi.pro zle_word.pro
X
XOBJS=builtin.o cond.o exec.o glob.o hist.o init.o jobs.o lex.o loop.o \
Xmath.o mem.o params.o parse.o subst.o table.o text.o utils.o watch.o \
Xzle_bindings.o zle_hist.o zle_main.o zle_misc.o zle_move.o zle_refresh.o \
Xzle_tricky.o zle_utils.o zle_vi.o zle_word.o
X
XBINDIR=/usr/local/bin
XMANDIR=/usr/local/man/man1
X
X# Debugging flags
XDFLAGS = # -DQDEBUG
X
X# For gcc 2.3.3
X# CC=gcc -fpcc-struct-return
X# CFLAGS= -O2 -g -Wall -Wno-implicit -Wno-parentheses -Wno-comment $(DFLAGS)
X
XCC=cc
XCFLAGS= -O
XLIBS= -ltermcap
X
XZSHPATH=zsh
X
X.SUFFIXES: .c .o .pro
X
X.c.o:
X $(CC) $(CFLAGS) $(DFLAGS) -c $<
X
X.c.pro:
X sed -n '/\/\*\*\/$$/{N;s/^\([^(]*\).*\/\*\*\/.\(.*\)/\1 DCLPROTO((\2))/p;}' $< | sed -e 's/;/,/g' -e 's/,))$$/));/' -e 's/(({))$$/((void));/' >$@
X
Xall: $(PROTO) $(ZSHPATH)
X
X$(ZSHPATH): $(OBJS)
X $(CC) -o $(ZSHPATH) $(OBJS) $(LIBS) $(LFLAGS)
X
Xtags: /tmp
X ctags *.[cy]
X
X# I hate this next line
X$(OBJS): config.h zsh.h zle.h signals.h ztype.h funcs.h
X
Xparams.o: version.h
X
Xclean:
X rm -f *.o *.pro zsh core
X
Xcleanall:
X rm -f *.o *.pro zsh core Makefile signals.h config.h
X
Xinstall: zsh
X install -s -m 755 zsh $(BINDIR)
X install -m 444 ../man/man1/zsh.1 $(MANDIR)
END_OF_FILE
if test 1851 -ne `wc -c <'src/Makefile.sample'`; then
echo shar: \"'src/Makefile.sample'\" unpacked with wrong size!
fi
# end of 'src/Makefile.sample'
fi
echo shar: End of archive 3 \(of 22\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 22 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...