References
- Unix shell initialization
- Intrinsics
- Params
- Refer for difference between
$@
and$*
.
- Refer for difference between
- Guide. This is a longer guide but geared towards comprehensively addressing zsh from the user’s standpoint.
- Manual. This is a really long manual that covers everything you’d want to know about zsh, particularly if you’re a scripter you’ll like this one!
- Options
(such as
-e
, etc.) - Shell Builtin Commands
- typeset
declare
→typeset
export
→typeset -gx
integer
→typeset -i
readonly
→typeset -r
local
→typeset
typeset
creates local names by default. If you want to affect the name already in some parent scope, pass in-g
- The options
-g
, and-f
are not permitted. - In this case the
-x
option does not force the use of-g
, i.e. exported variables will be local to functions.
- Note that arrays currently cannot be assigned in typeset expressions, only scalars and integers.
- typeset
- Precommand Modifiers
- Shell Grammar
- zshparam
- Parameters Set By The Shell
- e.g.
zsh_eval_context
,ZSH_VERSION
- e.g.
- Parameters Set By The Shell
- Options
(such as
- Loops: Under Complex Commands
- Cheatsheet. For the lazy and impatient! (though it’s upside down… sorry, not my fault!)
- FAQ. Great for those whiny questions that go like “Waah, why does zsh do X and Y differently from my old shell?”
- Special characters – reference
- zshwiki.org: Wiki Faq
- Job Control Options
- auto_resume, bg_nice, hup, notify, auto_continue, check_jobs
- Examples
- Argument Handling - OR: What's the deal with $* and $@?
- zargs, zmv, zpty
- Job Control Options
- Expansion
- Arithmetic Evaluation
- Precommand Modifiers
- Redirection
- Simple Commands & Pipelines
- Pipelines
- mattfoster's zshkit at master - GitHub
- show current git branch in zsh - Bart's Blog
- A User's Guide to the Z-Shell
- Large and nice looking, but from 2003 so keep that in mind.
- Sample .zshrc
- 10 more zsh tricks you may not know... (chneukirchen.com)
- zle: Zsh Line Editor
- Misc Shell
- https://github.com/zeekay/dot-zsh
- https://github.com/zeekay/dotfiles
- NOT zsh specific
Pages
Simple Commands and Pipelines
See: Simple Commands & Pipelines
If a sublist is terminated by a ‘&’, ‘&|’,
or ‘&!’
, the
shell executes the last pipeline in it in the background,
and does not wait for it to finish (note the difference from
other shells which execute the whole sublist in the
background).
Checkout
- Common idiom in scripts and functions:
: ${MYPARAM:=default} ${OTHERPARAM:=otherdefault}
If the user has already set $MYPARAM
, nothing happens, otherwise it will be set to default
, and similarly for ${OTHERPARAM}
. The :
command does nothing but return true after the command line has been processed.
-
One extremely useful zsh enhancement is the notation
${+foo}
which returns 1 if$foo
is set and 0 if it isn't. -
Most of the more sophisticated Bourne-like shells define two pairs of pattern operators, which I shall call
top and tail
operators. One pair (using#
and##
) removes a given pattern from the head of the string, returning the rest, while the other pair (using%
and%%
) removes a pattern from the tail of the string. In each case, the form with one symbol removes the shortest matching pattern, while the one with two symbols removes the longest matching pattern. Two typical uses are:% print $HOME /home/pws % print ${HOME##*/} pws % print ${HOME%/*} /home
which here have the same effect of ${HOME:t}
and and ${HOME:h}
, and in zsh you would be more likely to use the latter. However, as you can see the pattern forms are much more general. Note the difference from:
% print ${HOME#*/} home/pws % print ${HOME%%/*}
-
modifiers
-
% array=(~/.zshenv ~/.zshrc ~/.zlogout)
% print ${array:t}
.zshenv .zshrc .zlogout -
The final use of modifiers is in filename generation, i.e. globbing. Since this usually works by having special characters on the command line, and modifiers just consist of ordinary characters, the syntax is a little different:
% print *.c parser.c lexer.c input.c output.c % print *.c(:r) parser lexer input output
-
so you need parentheses around them. This is a special case of `glob qualifiers' which you'll meet below; you can mix them, but the modifiers must appear at the end. For example,
% print -l ~/stuff/* /home/pws/stuff/onefile.c /home/pws/stuff/twofile.c /home/pws/stuff/subdir % print ~/stuff/*(.:r:t) onefile twofile
The globbing qualifier .
specifies that files must be regular, i.e. not directories nor some form of special file. The :r
removes the suffix from the result, and the :t
takes away the directory part.
foo.c(:r)
will only strip off the suffix if foo.c
is there in the current directory. This is perfectly logical given that the attempt to match a file kicks the globbing system, including modifiers, into action. If this is a problem for you, there are ways round; for example, insert the right value by hand in a simple case like this, or more realistically store the value in a parameter and apply the modifier to that.
- More control over splitting and joining is possible with three of the more standard type of flags,
(s)
,(j)
and(z)
. These do splitting on a given string, joining with a given string, and splitting just the way the shell does it, respectively. In the first two cases, you need to specify the string in the same way as you specified the index for the(I)
flag. So, for example, here's how to turn$PATH
into an ordinary array without using$path
:% print -l ${(s.:.)PATH} /home/pws/bin /usr/local/bin /usr/sbin /sbin /bin /usr/bin /usr/X11R6/bin /usr/games
Any character can follow the (s)
or (j)
; the string argument lasts until the matching character, here .
. If the character is one of the bracket-like characters including <
, the matching' character is the corresponding right bracket, e.g.
${(s<:>)PATH}and
${(s(:))PATH}are both valid. This applies to all flags that need arguments, including
(I)`.
Although the split or join string isn't a pattern, it doesn't have to be a single character:
% foo=(array of words) % print ${(j.**.)foo} array**of**words
The (z)
flag doesn't take an argument. As it handles splitting on the full shell definition of a word, it goes naturally with quoted expressions, and I discussed above its use with the (Q)
flag for extracting words from a line with the quotes removed.
It's possible for the same parameter expression to have both splitting and joining applied to it. This always occurs in the same order, regardless of how you specify the flags: joining first, then splitting. This is described in the (rather hairy) complete set of rules in the manual entry for parameter substitution. There are one or two occasions where this can be a bit surprising. One is when you have SH_WORD_SPLIT
set and try to join a string:
% setopt shwordsplit % foo=('another array' of 'words with spaces') % print -l ${(j.:.)foo} another array:of:words with spaces
You might not have noticed if you didn't use the `-l
option to print, but the spaces still caused word-spliting even though you asked for the array to be joined with colons. To avoid this, either don't use SH_WORD_SPLIT
(my personal preference), or use quotes:
% print -l "${(j.:.)foo}" another array:of:words with spaces
The elements of an array would normally be joined by spaces in this case, but the character specified by the (j)
flag takes precedence. In just the same way, if SH_WORD_SPLIT
is in effect, any splitting string given by (s)
is used instead of the normal set of characters, which are any characters that occur in the string $IFS
, by default space, tab, newline and NUL.
Specifying a split for a particular parameter substitution not only sets the string to split on, but also ensures the split will take place even if the expression is quoted:
% array=('element one' 'element two' 'element three') % print -l "${=array}" element one element two element three
To be clear about what's happening here: the quotes force the elements to be joined with spaces, giving a single string, which is then split on the original spaces as well as the one used to join the elements of the array.
I will talk shortly about nested parameter substitution; you should also note that splitting and joining will if necessary take place at all levels of a nested substitution, not just the outermost one:
% foo="three blind words" % print ${#${(z)foo}} 3
This prints the length of the innermost expression; because of the zplit, that has produced a three-element array.
-
completion
-
for the kill command
- compctl -j -P % -x 'p1 s[-]' -k signals -- kill
-
for hosts
-
hosts=(valour cushioned myrddin tacitus chiark \
mercury.elmailer.net wigwam.elmail.co.uk sunsite.doc.ic.ac.uk \
ftp.uu.net ftp.sendmail.org tlingit.elmail.co.uk)
ssh=(chiark)
compctl -k ssh ssh
compctl -k hosts telnet ftp rlogin rsh ping traceroute
compctl -k hosts -f rcp scp -
OR
- compctl -x "n[1,~]" -u -S "/" - "n[1,//]" -k hosts -S "/" - "s[]" \
-f -k "(http:// ftp:// gopher:// telnet:// wais://)" -S "" \
-- lynx Mosaic netscape
compctl -x "n[1,~]" -u -S "/" - "n[1,//]" -k hosts -S "/" - "s[]" \
-k "(http:// ftp://)" -S "" -- wget rftp
-
-
-
redirection
-
There are also extra redirection methods, like:
% ghostview =( zcat /usr/man/man8/pppd.8.gz | groff -man )
which creates a temporary file for ghostview to display pages from
-
-
bindkey command
- define hotkeys!