home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume35
/
zsh
/
part02
< prev
next >
Wrap
Text File
|
1993-02-20
|
56KB
|
1,963 lines
Newsgroups: comp.sources.misc
From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Subject: v35i052: zsh - The Z Shell, version 2.3.1, Part02/22
Message-ID: <1993Feb20.211944.28059@sparky.imd.sterling.com>
X-Md4-Signature: fdc3c4b0c4ed6f6b753a3d0016f32119
Date: Sat, 20 Feb 1993 21:19:44 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Posting-number: Volume 35, Issue 52
Archive-name: zsh/part02
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.troff.01 dots/zshrc
# 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 2 (of 22)."'
if test -f 'doc/intro.troff.01' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/intro.troff.01'\"
else
echo shar: Extracting \"'doc/intro.troff.01'\" \(49835 characters\)
sed "s/^X//" >'doc/intro.troff.01' <<'END_OF_FILE'
X.nr PI 0
X.nr HM .5i
X.nr FM .5i
X.de Ds
X.DS L
X.ft C
X..
X.de De
X.DE
X\fR
X..
X.de DZ
X.DE
X\fR
X..
X.TL
XAn Introduction to the Z Shell
X.AU
XPaul Falstad
Xpf@ttisms.com
X.PP
X\fBzsh\fR is a shell designed for interactive use, although it
Xis also a powerful scripting language. Many of the useful
Xfeatures of bash, ksh, and tcsh were incorporated into zsh;
Xmany original features were added.
XThis document details some of the unique features of zsh.
XIt assumes basic knowledge of the standard UNIX shells;
Xthe intent is to show a reader already familiar with one of the
Xother major shells what makes zsh more useful or more powerful.
XThis document is not at all comprehensive; read the manual entry
Xfor a description of the shell that is
Xcomplete and concise,
Xalthough somewhat overwhelming and devoid of examples.
X.SH
XFilename Generation
X.PP
XOtherwise known as \fIglobbing\fR, filename generation
Xis quite extensive in zsh. Of course, it has all the
Xbasics:
X.Ds
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.DZ
XAlso, if the \fIEXTENDEDGLOB\fR option is set,
Xsome new features are activated.
XFor example, the \fC^\fR character negates the pattern following it:
X.Ds
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.DZ
XAn expression of the form
X\fC<\fIx\fR\-\fIy\fC>\fR
Xmatches a range of integers:
X.Ds
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.DZ
XGrouping is possible:
X.Ds
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.DZ
XAlso, the string \fC**/\fR forces a recursive search of
Xsubdirectories:
X.Ds
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.De
X.PP
XIt is possible to exclude certain files from the patterns using
Xthe ~ character. A pattern of the form \fC*.c~bar.c\fP lists all
Xfiles matching \fC*.c\fP, except for the file \fCbar.c\fP.
X.Ds
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.De
X.PP
XOne can add a number of \fIqualifiers\fR to the end of
Xany of these patterns, to restrict matches to certain
Xfile types. A qualified pattern is of the form
X.DS
X\fIpattern\fC(\fR...\fC)\fR
X.De
Xwith single-letter qualifiers inside the parentheses.
X.Ds
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.DZ
XNote that \fC*(x)\fR and \fC*(*)\fR both match executables.
X\fC*(X)\fR matches files executable by others, as opposed to
X\fC*(x)\fR, which matches files executable by the owner.
X\fC*(R)\fR and \fC*(r)\fR match readable files;
X\fC*(W)\fR and \fC*(w)\fR, which checks for writable files.
X\fC*(W)\fR is especially important, since it checks for world-writable
Xfiles:
X.Ds
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.DZ
XYou can filter out the symbolic links with the \fC^\fR character:
X.Ds
X% l *(W^@)
Xrun240
X% l *(x)
Xfoo* link@ morestuff/ stuff/
X% l *(x^@/)
Xfoo*
X.DZ
XTo find all plain files, you can use \fC.\fR:
X.Ds
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.DZ
X\fC*(U)\fR matches all files owned by you.
XTo search for all files not owned by you, use \fC*(^U)\fR:
X.Ds
X% l -l *(^U)
X-rw------- 1 subbarao 29 May 23 18:13 sub
X.DZ
XThis searches for setuid files:
X.Ds
X% l -l *(s)
X-rwsr-xr-x 1 pfalstad 16 May 23 18:12 foo*
X.DZ
XThis checks for a certain user's files:
X.Ds
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.De
X.SH
XStartup Files
X.PP
XThere are five startup files that zsh will read commands from:
X.Ds
X$ZDOTDIR/.zshenv
X$ZDOTDIR/.zprofile
X$ZDOTDIR/.zshrc
X$ZDOTDIR/.zlogin
X$ZDOTDIR/.zlogout
X.DZ
XIf \fBZDOTDIR\fR is not set, then the value of \fBHOME\fR is used;
Xthis is the usual case.
X.\".KE <--- missing .KS or .KF above
X.PP
X\&\fC.zshenv\fR is sourced on all invocations of the shell,
Xunless the \fC-f\fR option is set. It should contain commands to set
Xthe command search path, plus other important environment
Xvariables.
X\&\fC.zshenv\fR should not contain commands that produce output
Xor assume the shell is attached to a tty.
X.PP
X\&\fC.zshrc\fR is sourced in interactive shells. It should contain
Xcommands to set up aliases, functions, options, key bindings, etc.
X.PP
X\&\fC.zlogin\fR is sourced in login shells. It should contain
Xcommands that should be executed only in login shells.
X\&\fC.zlogout\fR is sourced when login shells exit.
X\&\fC.zprofile\fR is similar to \fC.zlogin\fR, except that it is sourced before
X\&\fC.zshrc\fR.
X\&\fC.zprofile\fR is meant as an alternative to \fC.zlogin\fR for
Xksh fans;
Xthe two are not intended to be used together, although this
Xcould certainly be done if desired.
X\&\fC.zlogin\fR is not the place for alias definitions, options, environment
Xvariable settings, etc.;
Xas a general rule, it should not change the shell environment
Xat all. Rather, it should be used to set the terminal type
Xand run a series of external commands (\fCfortune\fR, \fCmsgs\fR, etc).
X.SH
XShell Functions
X.PP
Xzsh also allows you to create your own commands by defining shell
Xfunctions. For example:
X.Ds
X% yp () {
X> ypmatch $1 passwd.byname
X> }
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X.DZ
XThis function looks up a user in the NIS password map.
XThe \fC$1\fR expands to the first argument to \fCyp\fR.
XThe function could have been equivalently defined in one of the following
Xways:
X.Ds
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.DZ
XNote that aliases are expanded when the function definition is
Xparsed, not when the function is executed. For example:
X.Ds
X% alias ypmatch=echo
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X.DZ
XSince the alias was defined after the function was parsed, it has
Xno effect on the function's execution.
XHowever, if we define the function again with the alias in place:
X.Ds
X% function yp () { ypmatch $1 passwd.byname }
X% yp pfalstad
Xpfalstad passwd.byname
X.DZ
Xit is parsed with the new alias definition in place.
XTherefore, in general you must define aliases before functions.
X.\".KE <--- missing .KS or .KF above
X.PP
XWe can make the function take multiple arguments:
X.Ds
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.DZ
XThe \fCfor i\fR loops through each of the function's arguments,
Xsetting \fCi\fR equal to each of them in turn.
XWe can also make the function do something sensible
Xif no arguments are given:
X.Ds
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.DZ
X\fC$#\fR is the number of arguments supplied to the function.
XIf it is equal to zero, we print a usage message; otherwise,
Xwe loop through the arguments, and \fCypmatch\fR all of them.
X.\".KE <--- missing .KS or .KF above
X.PP
XHere's a function that selects a random line from a file:
X.Ds
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.De
X\fCrandline\fR has a local variable, \fCz\fR, that holds the number of
Xlines in the file. \fC$[RANDOM % z + 1]\fR expands to a random number
Xbetween 1 and \fCz\fR. An expression of the form \fC$[\fR...\fC]\fR
Xexpands to the value of the arithmetic expression within the brackets,
Xand the \fBRANDOM\fR variable returns a random number each time it
Xis referenced. \fC%\fR is the modulus operator, as in C.
XTherefore, \fCsed -n $[RANDOM%z+1]p\fR picks a random line from its
Xinput, from 1 to \fCz\fR.
X.PP
XFunction definitions can be viewed with the \fCfunctions\fR builtin:
X.Ds
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.DZ
XHere's another one:
X.Ds
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.DZ
XNote that this could also have been implemented as an alias:
X.Ds
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.De
X.PP
XInstead of defining a lot of functions in your \fC.zshrc\fR,
Xall of which you may not use,
Xit is often better to use the \fCautoload\fR builtin.
XThe idea is, you create a directory where function
Xdefinitions are stored, declare the names in
Xyour \fC.zshrc\fR, and tell the shell where to look for them.
XWhenever you reference a function, the shell
Xwill automatically load it into memory.
X.Ds
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.De
XThis idea has other benefits. By adding a \fC#!\fR header
Xto the files, you can make them double as shell scripts.
X(Although it is faster to use them as functions, since a
Xseparate process is not created.)
X.Ds
X% ed /tmp/funs/yp
X25
Xi
X#! /usr/local/bin/zsh
X.
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.De
XNow other people, who may not use zsh, or who don't want to
Xcopy all of your \fC.zshrc\fR, may use these functions as shell
Xscripts.
X.SH
XDirectories
X.PP
XOne nice feature of zsh is the way it prints directories.
XFor example, if we set the prompt like this:
X.Ds
Xphoenix% PROMPT='%~> '
X~> cd src
X~/src>
X.De
Xthe shell will print the current directory in the prompt,
Xusing the \fC~\fR character.
XHowever, zsh is smarter than most other shells in this respect:
X.Ds
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.De
XNote that zsh prints \fIother\fR users' directories
Xin the form \fC~user\fR. Also note that you can
Xset a parameter and use it as a directory name;
Xzsh will act as if \fCfoo\fR is a user
Xwith the login directory \fC/usr/princeton/common/src\fR.
XThis is convenient, especially if you're sick of seeing
Xprompts like this:
X.Ds
Xphoenix:/usr/princeton/common/src/X.V11R4/contrib/clients/xv/docs>
X.DZ
XIf you get stuck in this position, you can give the current
Xdirectory a short name, like this:
X.Ds
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.De
XWhen you reference a directory in the form \fC~inews\fR,
Xthe shell assumes that you want the directory displayed
Xin this form; thus simply typing \fCecho ~inews\fR or
X\fCcd ~inews\fR causes the prompt to be shortened.
XYou can define a shell function for this purpose:
X.Ds
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.De
XYou may want to add this one-line function to your \fC.zshrc\fR.
X
Xzsh can also put the current directory in your title bar,
Xif you are using a windowing system.
XOne way to do this is with the \fCchpwd\fR function, which is
Xautomatically executed by the shell whenever you change
Xdirectory. If you are using xterm, this will work:
X.Ds
Xchpwd () { print -Pn '^[]2;%~^G' }
X.De
XThe \fC-P\fR option tells \fCprint\fR to treat its arguments like a prompt
Xstring; otherwise the \fC%~\fR would not be expanded.
XThe \fC-n\fR option suppresses the terminating newline, as with \fCecho\fR.
X.PP
XIf you are using an IRIS \fCwsh\fR, do this:
X.Ds
Xchpwd () { print -Pn '^[P1.y%~^[\' }
X.DZ
XThe \fCprint -D\fR command has other uses. For example, to
Xprint the current directory to standard output in short form,
Xyou can do this:
X.Ds
X% print -D $PWD
X~subbarao/src
X.DZ
Xand to print each component of the path in short form:
X.Ds
X% print -D $path
X/bin /usr/bin ~locbin ~locbin/X11 ~/bin
X.De
X.SH
XDirectory Stacks
X.PP
XIf you use csh, you may know about directory stacks.
XThe \fCpushd\fR command puts the current directory on the
Xstack, and changes to a new directory; the \fCpopd\fR command
Xpops a directory off the stack and changes to it.
X.Ds
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.De
Xzsh's directory stack commands work similarly. One
Xdifference is the way \fCpushd\fR is handled if no arguments
Xare given. As in csh, this exchanges the top two elements
Xof the directory stack:
X.Ds
XZ /tmp> dirs
X/tmp ~
XZ /tmp> pushd
X~ /tmp
X.DZ
Xunless the stack only has one entry:
X.Ds
XZ ~> popd
X/tmp
XZ /tmp> dirs
X/tmp
XZ /tmp> pushd
X~ /tmp
X.DZ
Xor unless the \fIPUSHDTOHOME\fR option is set:
X.Ds
XZ ~> setopt pushdtohome
XZ ~> pushd
X~ ~ /tmp
X.De
X.PP
XAs an alternative to using directory stacks in this manner,
Xwe can get something like a \fIdirectory history\fR
Xby setting a few more options and parameters:
X.Ds
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.De
XNote that \fC=2\fR expanded to the second directory in the
Xhistory list, and that \fCcd -3\fR recalled the third
Xdirectory in the list.
X.PP
XYou may be wondering what all those options do.
X\fIAUTOPUSHD\fR made \fCcd\fR act like \fCpushd\fR.
X(\fCalias cd=pushd\fR is not sufficient, for various reasons.)
X\fIPUSHDMINUS\fR swapped the meaning of \fCcd +1\fR and
X\fCcd -1\fR; we want them to mean the opposite of what they mean in csh,
Xbecause it makes more sense in this scheme, and it's easier to type:
X.Ds
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.De
X\fIPUSHDSILENT\fR keeps the shell from printing
Xthe directory stack each time we do a \fCcd\fR,
Xand \fIPUSHDTOHOME\fR we mentioned earlier:
X.Ds
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.DZ
X\fBDIRSTACKSIZE\fR keeps the directory stack
Xfrom getting too large, much like \fIHISTSIZE\fR:
X.Ds
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.De
X.SH
XCommand/Process Substitution
X.PP
XCommand substitution in zsh can take two forms.
XIn the traditional form, a command enclosed in
Xbackquotes (\fC`\fR...\fC`\fR) is replaced on the command line with its output.
XThis is the form used by the older shells.
XNewer shells (like zsh) also provide another form,
X\fC$(\fR...\fC)\fR. This form is much easier to nest.
X.Ds
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.DZ
XMany common uses of command substitution, however, are
Xsuperseded by other mechanisms of zsh:
X.Ds
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.DZ
XA command name with a \fC=\fR prepended is replaced with its full
Xpathname. This can be very convenient. If it's not convenient
Xfor you, you can turn it off:
X.Ds
X% ls
X=foo =bar
X% ls =foo =bar
Xzsh: foo not found
X% setopt noequals
X% ls =foo =bar
X=foo =bar
X.De
X.PP
XAnother nice feature is process substitution:
X.Ds
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.De
XA command of the form \fC=(\fR...\fC)\fR is replaced with the name of a \fIfile\fR
Xcontaining its output. (A command substitution, on the other
Xhand, is replaced with the output itself.)
X\fCprint -l\fR is like \fCecho\fR, excepts that it prints its arguments
Xone per line, the way \fCfgrep\fR expects them:
X.Ds
X% print -l foo bar
Xfoo
Xbar
X.DZ
XWe could also have written:
X.Ds
X% who | fgrep -f =(echo 'root
X> lemke
X> shgchan
X> subbarao')
X.DZ
XUsing process substitution,
Xyou can edit the output of a command:
X.Ds
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.DZ
Xor easily read archived mail:
X.Ds
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.DZ
XNote that the shell creates a temporary file, and deletes it
Xwhen the command is finished.
X.Ds
X% diff =(ls) =(ls -F)
X3c3
X< fortune
X---
X> fortune*
X10c10
X< strfile
X---
X> strfile*
X.De
XIf you read zsh's man page, you may notice that \fC<(\fR...\fC)\fR
Xis another form of process substitution which is similar to
X\fC=(\fR...\fC)\fR.
XThere is an important difference between the two.
XIn the \fC<(\fR...\fC)\fR case, the shell creates a named pipe (FIFO)
Xinstead of a file. This is better, since it does not
Xfill up the file system; but it does not work in all cases.
XIn fact, if we had replaced \fC=(\fR...\fC)\fR with \fC<(\fR...\fC)\fR in
Xthe examples above, all of them would have stopped working
Xexcept for \fCfgrep -f <(\fR...\fC)\fR.
XYou can not edit a pipe, or open it as a mail folder;
X\fCfgrep\fR, however, has no problem with reading
Xa list of words from a pipe.
XYou may wonder why \fCdiff <(foo) bar\fR doesn't work, since
X\fCfoo | diff - bar\fR works; this is because \fCdiff\fR creates
Xa temporary file if it notices that one of its arguments
Xis \fC-\fR, and then copies its standard input to the temporary
Xfile.
X.SH
XAliasing
X.PP
XOften-used commands can be abbreviated with an alias:
X.Ds
X% alias uc=uncompress
X% ls
Xhanoi.Z
X% uc hanoi
X% ls
Xhanoi
X.DZ
Xor commands with certain desired options:
X.Ds
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\fR...
X.DZ
XAliases can also be used to replace old commands:
X.Ds
X% alias grep=egrep ps=sps make=gmake
X% alias whoami='echo root'
X% whoami
Xroot
X.DZ
Xor to define new ones:
X.Ds
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.De
X(The pattern \fC*(R)\fR matches all readable files in the current
Xdirectory, and \fC*(^R)\fR matches all unreadable files.)
X.PP
XMost other shells have aliases of this kind (\fIcommand\fR aliases).
XHowever, zsh also has \fIglobal\fR aliases, which are substituted
Xanywhere on a line.
XGlobal aliases can be used to abbreviate frequently-typed
Xusernames, hostnames, etc.
X.Ds
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.DZ
XHere are some more interesting uses.
X.Ds
X% alias -g M='| more' GF='| fgrep -f ~/.friends'
X% who M # \fIpipes the output of \fCwho\fI through \fCmore
X% who GF # \fIsee if your friends are on\fC
X% w GF # \fIsee what your friends are doing
X.DZ
XAnother example makes use of zsh's process substitution.
XIf you run NIS, and you miss being able to do this:
X.Ds
X% grep pfalstad /etc/passwd
X.DZ
Xyou can define an alias that will seem more natural
Xthan \fCypmatch pfalstad passwd\fR:
X.Ds
X% alias -g PASS='<(ypcat passwd)'
X% grep pfalstad PASS
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X.DZ
XIf you're really crazy, you can even call it \fC/etc/passwd\fR:
X.Ds
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.De
XThe last example shows one of the perils of global aliases;
Xthey have a lot of potential to cause confusion.
XFor example, if you defined a global alias called \fC|\fR (which is
Xpossible), zsh would begin to act very strangely; every pipe
Xsymbol would be replaced with the text of your alias.
XTo some extent, global aliases are like macros in C;
Xdiscretion is advised in using them and in choosing names for them.
XUsing names in all caps is not a bad idea, especially
Xfor aliases which introduce shell metasyntax (like \fCM\fR and \fCGF\fR
Xabove).
X.PP
XNote that zsh aliases are not like csh aliases. The syntax for
Xdefining them is different, and they do not have arguments.
XAll your favorite csh aliases will probably not work under zsh.
XFor example, if you try:
X.Ds
Xalias rm mv '\e!* /tmp/wastebasket'
X.De
Xno aliases will be defined, but zsh will not report an error.
XIn csh, this line defines an alias that makes \fCrm\fR safe---files
Xthat are \fCrm\fR'd will be moved to a temporary directory instead
Xof instantly destroyed. In zsh's syntax, however, this line
Xasks the shell to print any existing alias definitions for \fCrm\fR, \fCmv\fR,
Xor \fC!* /tmp/wastebasket\fR. Since there are none, most likely,
Xthe shell will not print anything, although \fCalias\fR will
Xreturn a nonzero exit code.
XThe proper syntax is this:
X.Ds
Xalias rm='mv \e!* /tmp/wastebasket'
X.DZ
XHowever, this won't work either:
X.Ds
X% rm foo.dvi
Xzsh: no matches found: !*
X.DZ
XWhile this makes \fCrm\fR safe, it is certainly not what the user
Xintended. In zsh, you must use a shell function for this:
X.Ds
X% unalias rm
X% rm () { mv $* /tmp/wastebasket }
X% rm foo.dvi
X% ls /tmp/wastebasket
Xfoo.dvi
X.DZ
XWhile this is much cleaner and easier to read (I hope you will
Xagree), it is not csh-compatible. Therefore, a script to convert
Xcsh aliases and variables has been provided. You should only need to use it
Xonce, to convert all your csh aliases and parameters to zsh format:
X.Ds
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.De
XThe first two aliases were converted to regular zsh aliases, while
Xthe third, since it needed to handle arguments, was converted to
Xa function. \fCc2z\fR can convert most aliases to zsh format without
Xany problems. However, if you're using some really arcane csh tricks,
Xor if you have an alias with a name like \fCdo\fR (which is reserved
Xin zsh), you may have to fix some of the aliases by hand.
X.PP
XThe \fCc2z\fP script checks your csh setup, and produces a list
Xof zsh commands which replicate your aliases and parameter settings
Xas closely as possible. You could include its output in your
Xstartup file, \fC.zshrc\fP.
X.SH
XHistory
X.PP
XThere are several ways to manipulate history in zsh.
XOne way is to use csh-style \fC!\fR history:
X.Ds
X% /usr/local/bin/!:0 !-2*:s/foo/bar/ >>!$
X.De
XIf you don't want to use this, you can turn it off
Xby typing \fCsetopt nobanghist\fR.
X.PP
XAnother way is to use the \fCfc\fR command. For example,
Xif you type an erroneous command:
X.Ds
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\fR...
X.DZ
Xtyping \fCfc\fR will execute an editor on this command, allowing
Xyou to fix it. (The default editor is \fCvi\fR, by the way,
Xnot \fCed\fR).
X.Ds
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\fR...
X.DZ
XA variant of the \fCfc\fR command is \fCr\fR, which redoes the last
Xcommand, with optional changes:
X.Ds
X% echo foo
Xfoo
X% r
Xecho foo
Xfoo
X
X% echo foo
Xfoo
X% r foo=bar
Xecho bar
Xbar
X.De
X.SH
XCommand Line Editing
X.PP
Xzsh's command line editor, \fBZLE\fP, is quite powerful.
XIt is designed to emulate either emacs or vi; the default
Xis emacs. To set the bindings for vi mode, type \fCbindkey -v\fR.
X.PP
XIn addition to basic editing, the shell allows you to
Xrecall previous lines in the history. In emacs mode,
Xthis is done with \fI^P\fP (control-P):
X.Ds
X% ls ~
X- README file mail pub tmp
XMailboxes bin func nicecolors scr zsh
XNews etc iris notes src
X% echo foobar
Xfoobar
X% \fI^P\fC
X% echo foobar\fI^P\fC
X% ls ~_
X.De
XPressing \fI^P\fP once brings up the previous line (\fCecho foobar\fR);
Xpressing it again brings up the line before that (\fCls ~\fR).
XThe cursor is left at the end of the line, allowing you to
Xedit the line if desired before executing it.
XIn many cases, \fBZLE\fP eliminates the need for the \fCfc\fR command,
Xsince it is powerful enough to handle even multiline commands:
X.Ds
X% for i in a b c d e
X> do
X> echo $i
X> done
Xa
Xb
Xc
Xd
Xe
X% \fI^P\fC
X% for i in a b c d e
X do
X echo $i
X done_
X.DZ
XNow you can just move up to the part you want to change...
X.Ds
X% for i in \kxa\l'|\nxu\(ul' b c d e
X do
X echo $i
X done
X.DZ
Xchange it, and execute the new command.
X.Ds
X% for i in f g h i j
X do
X echo $i
X done
Xf
Xg
Xh
Xi
Xj
X.DZ
XAlso, you can search the history for a certain command using
X\fIESC-P\fR:
X.Ds
X% set \fIESC-P\fC
X% setopt autolist \fIESC-P\fC
X% setopt nocorrect_
X.DZ
XAnother way is to do an incremental search, emacs-style:
X.Ds
X% \fI^R\fC
X% _
Xi-search:
X
X% l\kxs\l'|\nxu\(ul' /usr/bin
Xi-search: l
X
X% date > foofile\kx.\l'|\nxu\(ul'c
Xi-search: le
X.DZ
XAnother useful feature of the editor is command and filename completion.
X.Ds
X% comp\fITAB\fC
X% compress _
X
X% ls /nic\fITAB\fC
X% ls /nicecolors _
X
X% ls /usr/pr\fITAB\fC
X% ls /usr/princeton/_
X
X% ls -l =com\fITAB\fC
X% ls -l =compress _
X.DZ
XIf the completion is ambiguous, the editor will beep.
XYou can list possible completions by pressing \fI^D\fP:
X.Ds
X% ls /vmu\fITAB \(embeep\(em\fC
X% ls /vmunix_
X% ls /vmunix\fI^D\fC
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X.DZ
XOr, you could just set the \fIAUTOLIST\fR option:
X.Ds
X% setopt autolist
X% ls /vmu\fITAB \(embeep\(em\fC
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_
X.De
XAnother option you could set is \fIRECEXACT\fR, which causes
Xexact matches to be accepted, even if there are other possible
Xcompletions:
X.Ds
X% setopt recexact
X% ls /vmu\fITAB \(embeep\(em\fC
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_\fITAB\fC
X% ls /vmunix _
X.DZ
XThe \fIfignore\fR variable lists suffixes of files to ignore
Xduring completion.
X.Ds
X% ls foo\fITAB \(embeep\(em\fC
Xfoofile.c foofile.o
X% fignore=( .o \e~ .bak .junk )
X% ls foo\fITAB\fP
X% ls foofile.c _
X.De
XSince \fCfoofile.o\fR has a suffix that is in the \fCfignore\fR list,
Xit was not considered a possible completion of \fCfoo\fR.
X.PP
XUsername completion is also supported:
X.Ds
X% ls ~pfal\fITAB\fC
X% ls ~pfalstad/_
X.DZ
Xand parameter name completion:
X.Ds
X% echo $ORG\fITAB\fC
X% echo $ORGANIZATION _
X.DZ
Xand hostname completion, if you give the shell a list of hosts to
Xcomplete:
X.Ds
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 disk\fITAB\fC
X% telnet diskfarm.princeton.edu _
X
X% ftp uu\fITAB\fC
X% ftp uunet.uu.net _
X
X% mail subbarao@ph\fITAB\fC
X% mail subbarao@phoenix.princeton.edu _
X.DZ
Xand option completion:
X.Ds
X% setopt nocl\fITAB\fC
X% setopt noclobber _
X.DZ
Xand binding completion:
X.Ds
X% bindkey '^X^X' pu\fITAB\fC
X% bindkey '^X^X' push-line _
X.De
X.PP
XThe \fCcompctl\fP command is used to control how completion works.
XFor example, to specify that certain commands show take
Xcommands as arguments, you use \fCcompctl -c\fP:
X.Ds
X% compctl -c man nohup
X% man upt\fITAB\fC
X% man uptime _
X.De
XTo specify that a command should complete filenames, you should use
X\fCcompctl -f\fP. This is the default. It can be combined with \fC-c\fP,
Xas well.
X.Ds
X% compctl -cf echo
X% echo upt\fITAB\fC
X% echo uptime _
X
X% echo fo\fITAB\fC
X% echo foo.c
X.De
XSimilarly, use \fC-h\fP to specify hostnames, \fC-o\fP to specify
Xoptions, \fC-v\fP to specify variables, and \fC-b\fP to specify bindings.
X.Ds
X% compctl -h rlogin
X% compctl -hfc rsh
X% compctl -b bindkey
X.De
XYou can also use \fC-k\fP to specify a custom list of keywords to use
Xin completion.
X.Ds
X% ftphosts=(ftp.uu.net wuarchive.wustl.edu)
X% compctl -k ftphosts ftp
X% ftp wu\fITAB\fC
X% ftp wuarchive.wustl.edu _
X
X% friends=(cpirazzi subbarao sukthnkr)
X% compctl -k friends mail finger su
X% finger cp\fITAB\fC
X% finger cpirazzi _
X.De
X.PP
XIn addition to completion, \fITAB\fP performs expansion
Xif possible.
X.Ds
X% ls *.c\fITAB\fC
X% ls foofile.c fortune.c rnd.c strfile.c unstr.c_
X.DZ
XFor example, suppose you have a bunch of weird files in an important
Xdirectory:
X.Ds
X% ls
X * * * ; & % $??foo dspfok foo.c
X !"foo"! ` \e ` foo rrr
X.DZ
XYou want to remove them, but you don't want to damage \fCfoo.c\fR.
XHere is one way to do this:
X.Ds
X% rm *\fITAB\fC
X% rm \e \e \e*\e \e*\e \e*\e \e \e \e!\e"foo\e"\e! \e;\e \e&\e %\e \e$'
X''
X'foo \e`\e \e\e\e \e` dspfok foo foo.c rrr_
X.DZ
XWhen you expand \fC*\fR, zsh inserts the names of all the files
Xinto the editing buffer, with proper shell quoting.
XNow, just move back and remove \fCfoo.c\fR from the buffer:
X.Ds
X% rm \e \e \e*\e \e*\e \e*\e \e \e \e!\e"foo\e"\e! \e;\e \e&\e %\e \e$'
X''
X'foo \e`\e \e\e\e \e` dspfok foo \kxr\l'|\nxu\(ul'rr
X.De
Xand press return.
XEverything except \fCfoo.c\fR will be deleted from the directory.
X.PP
XHere's another trick; let's say you have typed this command in:
X.Ds
X% gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs_
X.De
Xand you forget which library you want. You need to escape
Xout for a minute and check by typing
X\fCls /usr/lib\fR, or some other such command;
Xbut you don't want to retype the whole command again,
Xand you can't press return now because the current command
Xis incomplete.
XIn zsh, you can put the line on the \fIbuffer stack\fR, using
X\fIESC-Q\fP, and type some other commands. The next time a prompt is printed,
Xthe \fCgcc\fR line will be popped off the stack and put
Xin the editing buffer automatically; you can then enter the
Xproper library name and press return (or, \fIESC-Q\fP again and look
Xfor some other libraries whose names you forgot).
X.PP
XA similar situation: what if you forget the option to gcc that
Xfinds bugs using AI techniques? You could either use \fIESC-Q\fP
Xagain, and type \fCman gcc\fR, or you could press \fIESC-H\fR, which
Xessentially does the same thing; it puts the current line on
Xthe buffer stack, and executes the command \fCrun-help gcc\fR,
Xwhere \fCrun-help\fR is an alias for \fCman\fR.
X.PP
XAnother interesting command is \fIESC-A\fR. This executes the
Xcurrent line, but retains it in the buffer, so that it appears
Xagain when the next prompt is printed.
XAlso, the cursor stays in the same place.
XThis is useful for executing a series of similar commands:
X.Ds
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.De
X.PP
XThe \fIESC-'\fR command is useful for managing the shell's quoting
Xconventions. Let's say you want to print this string:
X.Ds
Xdon't do that; type 'rm -rf \e*', with a \e before the *.
X.DZ
XAll that is necessary is to type it into the editing buffer:
X.Ds
X% don't do that; type 'rm -rf \e*', with a \e before the *.
X.DZ
Xpress \fIESC-'\fR (escape-quote):
X.Ds
X% 'don'\e''t do that; type '\e''rm -rf \e*'\e'', with a \e before the *.'
X.DZ
Xthen move to the beginning and add the \fCecho\fR command.
X.Ds
X% echo 'don'\e''t do that; type '\e''rm -rf \e*'\e'', with a \e before the *.'
Xdon't do that; type 'rm -rf \e*', with a \e before the *.
X.DZ
XLet's say you want to create an alias to do this \fCecho\fR command.
XThis can be done by recalling the line with \fI^P\fP and pressing \fIESC-'\fR again:
X.Ds
X% 'echo '\e''don'\e''\e'\e'''\e''t do that; type '\e''\e'\e'''\e''rm -rf
X\e*'\e''\e'\e'''\e'', with a \e before the *.'\e'''
X.DZ
Xand then move to the beginning and add the command to create
Xan alias.
X.Ds
X% alias zoof='echo '\e''don'\e''\e'\e'''\e''t do that; type '\e''\e'\e'''\e''rm
X-rf \e*'\e''\e'\e'''\e'', with a \e before the *.'\e'''
X% zoof
Xdon't do that; type 'rm -rf \e*', with a \e before the *.
X.De
X.PP
XAnother interesting option is \fIMENUCOMPLETE\fR. This affects the
Xway \fITAB\fP works. Let's look at the \fC/vmunix\fR example again:
X.Ds
X% setopt menucomplete
X% ls /vmu\fITAB\fC
X% ls /vmunix\fITAB\fC
X% ls /vmunix.new.kernelmap.old\fITAB\fC
X% ls /vmunix.old_
X.De
XEach time you press \fITAB\fP, it displays the next possible completion.
XIn this way, you can cycle through the possible completions until
Xyou find the one you want.
X.PP
XThe \fIAUTOMENU\fR option makes
Xa nice compromise between this method of completion and the regular
Xmethod. If you set this option, pressing the \fITAB\fP key repeatedly
Xafter an ambiguous completion will cycle through the possible
Xcompletions.
X.SH
XBindings
X.PP
XEach of the above editor commands was actually a function bound
Xby default to a certain key. The real names of the commands are:
X.Ds
X\fCexpand-or-complete \fITAB\fR
X\fCpush-line \fIESC-Q\fR
X\fCrun-help \fIESC-H\fR
X\fCaccept-and-hold \fIESC-A\fR
X\fCquote-line \fIESC-'\fR
X.DZ
XThese bindings are arbitrary; you could change them if you want.
XFor example, to bind \fCaccept-line\fR to \fI^Z\fP:
X.Ds
X% bindkey '^Z' accept-line
X.DZ
XAnother idea would be to bind the delete key to \fCdelete-char\fR;
Xthis might be convenient if you use \fI^H\fP for backspace.
X.Ds
X% bindkey '^?' delete-char
X.DZ
XOr, you could bind \fI^X\fP\fI^H\fP to \fCrun-help\fR:
X.Ds
X% bindkey '^X^H' run-help
X.DZ
XOther examples:
X.Ds
X% bindkey '^X^Z' universal-argument
X% bindkey ' ' magic-space
X% bindkey -s '^T' 'uptime
X> '
X.De
X\fCuniversal-argument\fR multiplies the next command by 4.
XThus \fI^X\fP\fI^Z\fP\fI^W\fP might delete the last four words on the line.
XIf you bind space to \fCmagic-space\fR, then csh-style history
Xexpansion is done on the line whenever you press the space bar.
X.PP
XThe \fC-s\fR flag to \fCbindkey\fR specifies that you are binding the key
Xto a string, not a command. Thus \fCbindkey -s '^T' 'uptime\en'\fR
Xlets you VMS lovers get the load average whenever you press \fI^T\fP.
X.PP
XIf you have a NeXT keyboard, the one with the \fC|\fR and \fC\e\fR keys
Xvery inconveniently placed, the following
Xbindings may come in handy:
X.Ds
X% bindkey -s '\ee/' '\e\e'
X% bindkey -s '\ee=' '|'
X.De
XNow you can type \fIALT-/\fP to get a backslash, and \fIALT-=\fP to
Xget a vertical bar. This only works inside zsh, of course;
X\fCbindkey\fR has no effect on the key mappings inside \fCtalk\fR
Xor \fCmail\fR, etc.
X.PP
XAnother use of the editor is to edit the value of variables.
XFor example, an easy way to change your path is to use
Xthe \fCvared\fR command:
X.Ds
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.De
XYou can now edit the path. When you press return, the contents
Xof the edit buffer will be assigned to \fBPATH\fR.
X.SH
XParameter Substitution
X.PP
XIn zsh, parameters are set like this:
X.Ds
X% foo=bar
X% echo $foo
Xbar
X.DZ
XSpaces before or after the \fC=\fR are frowned upon:
X.Ds
X% foo = bar
Xzsh: command not found: foo
X.DZ
XAlso, \fCset\fR doesn't work for setting parameters:
X.Ds
X% set foo=bar
X% set foo = bar
X% echo $foo
X
X%
X.De
XNote that no error message was printed. This is because both
Xof these commands were perfectly valid; the \fCset\fR builtin
Xassigns its arguments to the \fIpositional parameters\fR
X(\fC$1\fR, \fC$2\fR, etc.).
X.Ds
X% set foo=bar
X% echo $1
Xfoo=bar
X% set foo = bar
X% echo $3 $2
Xbar =
X.DZ
XIf you're really intent on using the csh syntax, define a
Xfunction like this:
X.Ds
X% set () {
X> eval "$1$2$3"
X> }
X% set foo = bar
X% set fuu=brrr
X% echo $foo $fuu
Xbar brrr
X.De
XBut then, of course you can't use the form of \fCset\fR with
Xoptions, like \fCset -F\fR (which turns off filename generation).
XAlso, the \fCset\fR command by itself won't list all the parameters
Xlike it should.
XTo get around that you need a \fCcase\fR statement:
X.Ds
X% set () {
X> case $1 in
X> -*|+*|'') builtin set $* ;;
X> *) eval "$1$2$3" ;;
X> esac
X> }
X.De
XFor the most part, this should make csh users happy.
X.PP
XThe following sh-style operators are supported in zsh:
X.Ds
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.DZ
XAlso, csh-style \fC:\fR modifiers may be appended to a parameter
Xsubstitution.
X.Ds
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.De
XThe equivalent constructs in ksh (which are also supported in zsh)
Xare a bit more general and easier to remember.
XWhen the shell expands \fC${foo#\fR\fIpat\fR\fC}\fR,
Xit checks to see if \fIpat\fR matches a substring at the beginning
Xof the value
Xof \fCfoo\fR. If so, it removes that portion of \fCfoo\fR, using the shortest
Xpossible match.
XWith \fC${foo##\fR\fIpat\fR\fC}\fR, the longest possible match is removed.
X\fC${foo%\fR\fIpat\fR\fC}\fR and \fC${foo%%\fR\fIpat\fR\fC}\fR remove the match
Xfrom the end.
XHere are the ksh equivalents of the \fC:\fR modifiers:
X.Ds
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.DZ
Xzsh also has upper/lowercase modifiers:
X.Ds
X% xx=Test
X% echo $xx:u
XTEST
X% echo $xx:l
Xtest
X.DZ
Xand a substitution modifier:
X.Ds
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.DZ
XOne possible source of confusion is the fact that in zsh,
Xthe result of parameter substitution is \fInot\fR split into
Xwords. Thus, this will not work:
X.Ds
X% srcs='glob.c exec.c init.c'
X% ls $srcs
Xglob.c exec.c init.c not found
X.DZ
XThis is considered a feature, not a bug.
XIf splitting were done by default, as it is in most other shells,
Xfunctions like this would not work properly:
X.Ds
X$ ll () { ls -F $* }
X$ ll 'fuu bar'
Xfuu not found
Xbar not found
X
X% ll 'fuu bar'
Xfuu bar not found
X.DZ
XOf course, a hackish workaround is available in sh (and zsh):
X.Ds
X% setopt shwordsplit
X% ll () { ls -F "$@" }
X% ll 'fuu bar'
Xfuu bar not found
X.DZ
XIf you like the sh behaviour, zsh can accomodate you:
X.Ds
X% ls ${=srcs}
Xexec.c glob.c init.c
X% setopt shwordsplit
X% ls $srcs
Xexec.c glob.c init.c
X.DZ
XAnother way to get the \fC$srcs\fR trick to work is to use an array:
X.Ds
X% unset srcs
X% srcs=( glob.c exec.c init.c )
X% ls $srcs
Xexec.c glob.c init.c
X.DZ
Xor an alias:
X.Ds
X% alias -g SRCS='exec.c glob.c init.c'
X% ls SRCS
Xexec.c glob.c init.c
X.DZ
XAnother option that modifies parameter expansion is
X\fIRCEXPANDPARAM\fR:
X.Ds
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.De
X.SH
XShell Parameters
X.PP
XThe shell has many predefined parameters that may be
Xaccessed. Here are some examples:
X.Ds
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.DZ
X(\fC$?\fR and \fC$status\fR are equivalent.)
X.Ds
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.DZ
X\fC~+\fR and \fC~-\fR are short for \fC$PWD\fR and \fC$OLDPWD\fR, respectively.
X.Ds
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.De
X.PP
XThe \fCcdpath\fR variable sets the search path for the \fCcd\fR command.
XIf you do not specify \fC.\fR somewhere in the path, it is assumed to
Xbe the first component.
X.Ds
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.DZ
X\fBPATH\fR and \fBpath\fR both set the search path for commands.
XThese two variables are equivalent, except that one is a string
Xand one is an array. If the user modifies \fBPATH\fR, the shell
Xchanges \fBpath\fR as well, and vice versa.
X.Ds
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.DZ
XThe same is true of \fBCDPATH\fR and \fBcdpath\fR:
X.Ds
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.DZ
END_OF_FILE
if test 49835 -ne `wc -c <'doc/intro.troff.01'`; then
echo shar: \"'doc/intro.troff.01'\" unpacked with wrong size!
fi
# end of 'doc/intro.troff.01'
fi
if test -f 'dots/zshrc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dots/zshrc'\"
else
echo shar: Extracting \"'dots/zshrc'\" \(2291 characters\)
sed "s/^X//" >'dots/zshrc' <<'END_OF_FILE'
X#
X# my rc file for zsh 2.2
X# all this runs in interactive shells only
X#
X
X# search path for the cd command
Xcdpath=(. ~ ~/src/cs320 ~/src)
X
X# where to look for function definitions
X# fpath=(~/func)
X
X# useful directory
Xcsrc=/usr/princeton/common/src
X
X# use hard limits, except for a smaller stack and no core dumps
Xunlimit
Xlimit stack 8192
Xlimit core 0
Xlimit -s
X
Xumask 022
X
X# define some aliases
Xalias a=alias
Xa a.out=./a.out sendmail=/usr/lib/sendmail c=cp 0=vi 09='vi -t' 00=r
Xa d=dirs en='enscript -2rGh' fm='finger -m' grep=egrep h=history
Xa hinfo='host -t hinfo' j=jobs l='ls -AF' lock='lock -p -60000'
Xa lsd='ls -d */' m=make mm=less
Xa nrable='ls -AFltrd *(^R)' sz='ls -l | sort -n +3 | tail -20'
Xa sn='sed -n' nw='l -ltr | tail' pd=pushd pop=popd mroe=more
Xa rable='ls -AFltrd *(R)' strings='strings -' t=cat
Xa v=mv where='hostname; echo >/dev/null' k9='kill -9' whoami='echo root'
Xa find='noglob find' bindkey='noglob bindkey' dh='dirs -v'
Xa mv='nocorrect mv' z=suspend
X
X# global aliases
Xa -g 'GF'='| fgrep -f ~/.friends' G='| grep' M='| less' cex='/u/pup/centrex'
X
X# setenv for csh junkies (including tset)
Xsetenv() { export $1=$2 }
X
Xmanpath=(/usr/man /usr/princeton/man /u/cad/man /usr/lang/man)
Xexport MANPATH
X
X# filename completion suffixes to ignore
Xfignore=(.o .pro .old)
X
X# hosts to use for completion
Xhosts=(uunet.uu.net `hostname` wuarchive.wustl.edu quiche.cs.mcgill.ca)
X
XPROMPT='%l %T %m[%h] '
X
X# prompt on the right side of the screen
XRPROMPT=' %~'
X
X# some environment variables
Xexport MAILCALL='NEW MAIL! '
Xexport YOUSAID='In %C you wrote:'
Xexport ATTRIBUTION='%f wrote:'
X
X# functions to autoload
X# autoload cx acx mere yu yp randline proto namedir ilogin
X
XMAILCHECK=30
XHISTSIZE=600
XDIRSTACKSIZE=50
X
X# lots of options
Xsetopt notify globdots correct pushdtohome cdablevars autolist \
X sunkeyboardhack correctall autocd recexact longlistjobs mailwarning \
X autoresume histignoredups pushdsilent noclobber \
X autopushd pushdminus extendedglob rcquotes
Xunsetopt bgnice
X
X# watch for my friends
Xwatch=($(cat ~/.friends))
XWATCHFMT='%n %a %l from %m at %t.'
XLOGCHECK=0
X
Xexport LESS=-ainx3
Xunhash p
X
X# some nice bindings
Xbindkey '^X^Z' universal-argument ' ' magic-space
Xbindkey '^X^A' vi-find-prev-char-skip
Xbindkey '^Z' accept-and-hold
Xbindkey -s '\M-/' \\\\
Xbindkey -s '\M-=' \|
END_OF_FILE
if test 2291 -ne `wc -c <'dots/zshrc'`; then
echo shar: \"'dots/zshrc'\" unpacked with wrong size!
fi
# end of 'dots/zshrc'
fi
echo shar: End of archive 2 \(of 22\).
cp /dev/null ark2isdone
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...