zsh

migration from bash

This is based on the man page included with Mac Os Montery 12.6 10/17/22. Official versions should be be viewed at SourceForge/zsh
As with all the documentation found on this website this is tersified.
This is a migration document, the reader is expeceted to be familiar with bash and Mac OS. FAQ (novella)
zsh.org

linux.die.net zshbuiltins

Overview
Intro
misc Anything not fitting into the other sections
expn command and parameter expansion
param parameters
options options
builtins built-in functions
zle command line editing
compwid completion widgets
compsys completion system
compctl completion control
modules loadable modules
tcpsys built-in TCP functions
zftpsys built-in FTP client ( Not in Mac version )
contrib Additional functions and utilities
all Meta-man page containing all of the above

Command interpreter (shell) is an interactive login shell and as a shell script command processor. Of the common shells, zsh resembles ksh with many enhancements. It does not provide compatibility with POSIX or other shells by default.

Includes command line editing, spelling correction, programmable command completion, shell functions (with autoloading) and history mechanism.

Entering ??????? provides an additional prompt execute:. To terminate enter ^g.

To set the default shell use chsh -s /bin/bash

prompt ?????

-i interactive. A script is permitted
-c First argument is a command , rather than reading commands from a script or standard input.
Second argument is assigned to $0.
-s Read commands from the standard input. Without -s argument is a script

Without -c or -s remaining arguments, after option processing, the first argument is a script

After the first one or two arguments, the remaining arguments are assigned to the positional parameters.

Options sourceForge

In that document: options that are set by default in all emulations are marked <D>efault;
those set by default only is some shell emulations are marked <C>sh, <K>sh, <S>h, <Z>sh .
Listing options: (with setopt, unsetopt, set -o or set +o),
> setopt
extendedhistory interactive interactivecomments login monitor shinstdin vi zle

sharing history across sessions (setopt SHARE_HISTORY), real-time appending (setopt INC_APPEND_HISTORY), extended history format (setopt EXTENDED_HISTORY), and substring search (often with plugins like zsh-history-substring-search), all configurable in ~/.zshrc to manage a persistent log of commands, stored in $HISTFILE with defined sizes (HISTSIZE, SAVEHIST). small> Now 5/2/25, I cannout determine where I got this list?.

zsh options

 unsetopt

noaliases
  aliasifuncdef


allexport
noalwayslastprompt
alwaystoend
appendcreate
noappendhistory 

autocd
autocontinue
noautolist
noautomenu
autonamedirs
noautoparamkeys
noautoparamslash
autopushd
noautoremoveslash
autoresume

nobadpattern
nobanghist
nobareglobqual
bashautolist 

 $bashrematch>


nobeep

braceccl
bsdecho
nocaseglob
nocasematch
casepaths
cbases
cdablevars
cdsilent
chasedots
chaselinks
nocheckjobs
nocheckrunningjobs
noclobber
clobberempty
combiningchars
completealiases
completeinword
continueonerror
correct
correctall
cprecedences

cshjunkiehistory
cshjunkieloops
cshjunkiequotes
cshnullcmd
cshnullglob
nodebugbeforecmd
dvorak
emacs
noequals
errexit
errreturn
noevallineno
noexec
extendedglob
noflowcontrol
forcefloat
nofunctionargzero
noglob
noglobalexport
noglobalrcs
globassign
globcomplete
globdots
globstarshort
globsubst
nohashcmds
nohashdirs
hashexecutablesonly
nohashlistall
histallowclobber

nohistbeep
histexpiredupsfirst
histfcntllock
histfindnodups
histignorealldups
histignoredups
histignorespace
histlexwords
histnofunctions
histnostore
histreduceblanks
nohistsavebycopy
histsavenodups
histsubstpattern
histverify

nohup
ignorebraces
ignoreclosebraces
ignoreeof 

ksharrays
kshautoload
kshglob
kshoptionprint
kshtypeset
kshzerosubscript
nolistambiguous
nolistbeep
listpacked
listrowsfirst
nolisttypes
localloops
localoptions
localpatterns
localtraps
longlistjobs
magicequalsubst
mailwarning
markdirs
menucomplete
nomultibyte
nomultifuncdef
nomultios
nonomatch
nonotify
nullglob
numericglobsort
octalzeroes
overstrike

pathdirs
pathscript
pipefail
posixaliases
posixargzero
posixbuiltins
posixcd
posixidentifiers
posixjobs
posixstrings
posixtraps
printeightbit
printexitvalue
privileged
promptbang
nopromptcr
nopromptpercent
nopromptsp
promptsubst

pushdignoredups
pushdminus
pushdsilent
pushdtohome


rcexpandparam
rcquotes
norcs
recexact
rematchpcre
restricted
rmstarsilent
rmstarwait
shfileexpansion
shglob
shnullcmd
shoptionletters
noshortloops
shortrepeat
shwordsplit
singlecommand
singlelinezle
sourcetrace
sunkeyboardhack
transientrprompt
trapsasync
typesetsilent
typesettounset
nounset
verbose
warncreateglobal
warnnestedvar
xtrace

grouped by function

noappendhistory
sharehistory
incappend
incappendhistorytime
histallowclobber
nohistbeep
histexpiredupsfirst
histfcntllock
histfindnodups
histignorealldups
histignoredups
histignorespace
histlexwords
histnofunctions
histnostore
histreduceblanks
nohistsavebycopy
histsavenodups
histsubstpattern
histverify
++

To use options by name use -o name []
For example:

 zsh -o shwordsplit scr 
runs the script scr with SH_WORD_SPLIT.

Options are turned off using +osic, `+-sh-word-split' is equivalent to `--no-sh-word-split'.

o can suffix single-letter options. Examples: `-xo shwordsplit' or `-xoshwordsplit' is equivalent to `-x -o shwordsplit'.

Options may be specified by name in long style --option-name. When this is done, dashes ( - ) in the option name are translated into underscores (_) and ignored.
for example, `zsh --sh-word-split' invokes zsh with SH_WORD_SPLIT .
Long options cannot be suffixes.

--version sends version information to standard output
--help sends a list of options that can be used when invoking the shell to standard output

To allow an argument to begin with a -, option processing is terminated with - , + , -- , +- or stacked with preceeding options (-x- is equivalent to -x --) .
`-b' or `+b' ends option processing. `-b' is like `--', except that further single-letter options can be stacked after the `-b'

Don't run bash scripts under zsh, if the scripts were written for bash add:

#!/usr/bin/env base 
scripts even if zsh is your shell for interactive sessions.

Biggies

Shell word splitting:

Arrays are (by default) : subscripts start at 1, not 0; array[0] refers to array[1]; $array refers to the whole array, not $array[0];
braces are unnecessary: $a[1] == ${a[1]}, etc.

Individual elements of arrays are always strings, not separate parameters.

Failure to match a globbing pattern causes an error (use NO_NOMATCH).

Parameter substitutions are treated as plain text: foo="*"; print $foo outputs * (use GLOB_SUBST).

Globbing:

     !(foo)            ^foo        Anything but foo.
                or   foo1~foo2     Anything matching foo1 but foo2[1].
@(foo1|foo2|...)  (foo1|foo2|...)  One of foo1 or foo2 or ...
     ?(foo)           (foo|)       0 or 1 occurrences of foo.
     *(foo)           (foo)#       0 or more occurrences of foo.
     +(foo)           (foo)##      1  or more occurrences of foo.

The ^, ~ and # (but not |)forms require EXTENDED_GLOB.

Unquoted assignments do file expansion after :s (intended for PATHs).

integer k=$(wc -l ~/.zshrc) does not work. the output from wc includes leading whitespace which causes wordsplitting.

Traps are not local to functions. use option LOCAL_TRAPS TRAPERR is TRAPZERR (which has SIGERR).

  # is not a comment in an interactive shell. Ugly for copy/paste script snippets.

From Differences. ed Jun 8, 2019 at 23:45 Gilles 'SO- stop being evil'

Configuration files:
.bash reads (mainly) .bashrc in non-login interactive shells .
 macOS starts a login shell in terminals by default), .profile or .bash_profile in login shells, and .inputrc.

 Zsh reads (mainly) .zshrc (in all interactive shells) and .zprofile (in login shells). This means that none of your bash customizations will apply: you'll need to port them over. You can't just copy the files because many things will need tweaking.

Key bindings use completely different syntax.
 Bash uses .inputrc and the bind builtin to bind keys to readline commands.
 Zsh uses the bindkey builtin to bind keys to zle widgets.

Most readline commands have a zsh equivalent, but it isn't always a perfect equivalence.

zsh defaults to vi editing mode. line mode in the shell, (i.e. with command and insert modes)

Prompt:
bash sets the prompt (mainly) from PS1 which may include backslash escapes.
Zsh sets the prompt mainly from which may include percent escapes.
The escape codes are completely different. The functionality of bash's PROMPT_COMMAND is available in zsh via the precmd and preexec hook functions.

command line history mechanisms (navigation with Up/Down, search with Ctrl+R, history expansion with !! and friends, last argument recall with Alt+. or $_) work in the same way, but there are a lot of differences in the detail

history control

Completion: completes command and file names, fancy mode by including bash_completion on bash or by running compinit in zsh. some commands bash handles better and some zsh handles better. Zsh is usually more precise, but sometimes gives up where bash does something that isn't correct but is sensible. To specify possible completions for a command, zsh : The “old” completion mechanism with compctl which you can forget about. The “new” completion mechanism with compadd and functions that begin with underscore and a powerful but complex user configuration mechanism. An emulation to support bash completion functions enable by running bashcompinit. isn't 100% perfect but it usually works. Many of bash's shopt settings have a corresponding setopt in zsh.

comments: Zsh doesn't treat # as a comment start on the command line by default, only in scripts (including .zshrc and such). run setopt interactive_comments.

scripting:

In bash, $foo takes the value of foo, splits it at whitespace characters, and for each whitespace-separated part, if it contains wildcard characters and matches an existing file, replaces the pattern by the list of matches. To get the value of foo, use "$foo". command substitution $(foo). In zsh, $foo is the value of foo and $(foo) is the output of foo minus its final newlines, with two exceptions. If a word becomes empty due to expanding empty unquoted variables, it's removed (e.g. a=; b=; printf "%s\n" one "$a$b" three $a$b five prints one, an empty line, three, five). The result of an unquoted command substitution is split at whitespace but the pieces don't undergo wildcard matching.

Arrays Bash are indexed from 0 to (length-1). Zsh arrays are indexed from 1 to length. setopt ksh_arrays makes 0-indexing the default with Zsh requires fewer braces (unless ksh_arrays is enabled). For example, suppose a=(first second third "" last).


Functionality   Bash syntax Idiomatic zsh syntax    Expansion
First element   ${a[0]} $a[1]   first
Second element  ${a[1]} $a[2]   second
Last element    ${a[${#a[@]}-1]}    $a[-1]  last
Length  ${#a[@]}    $#a 5
All the elements    "${a[@]}"   "${a[@]}" or "${(@)a}"  first second third (empty word) last
All the non-empty elements      $a  first second third last
Bash has extra wildcard patterns such as @(foo|bar) to match foo or bar, which are only enabled with shopt -s extglob..
In zsh, enable these patterns with setopt ksh_glob, but there's also a simpler-to-type native syntax such as (foo|bar), some of which require setopt extended_glob (Do put that in .zshrc, your and it's on by default in completion functions).

Zsh has **/ for recursive directory traversal.

Wildcard unmatch: In bash, by default, if a wildcard pattern doesn't match any file, it's left unchanged.
In zsh, by default, is an error .
to pass a wildcard parameter to a command, use quotes. setopt no_nomatch to the bash behavior setopt null_glob makes non-matching wildcard patterns expand to an empty list instead with

Pipe In bash, the right-hand side of a pipeline runs in a subshell. In zsh, it runs in the parent shell, so you can write things like somecommand | read output.

Some nice zsh features

bash doesn't have, a selection of the ones I consider the most useful.

Glob qualifiers allow matching files based on metadata such as their time stamp, size, etc.
They also allow tweaking the output. The syntax is rather cryptic, but it's extremely convenient. Examples:

foo*(.)  : only regular files matching foo* and symbolic links to regular files, not directories and other special files.
foo*(*.) : only executable regular files matching foo*.
foo*(-.) : only regular files matching foo*, not symbolic links and other special files.
foo*(-@) : only dangling symbolic links matching foo*.
foo*(om) : files matching foo*, sorted by last modification date, most recent first?.
foo*(om[1,10]) : 10 most recent files matching foo*, (sorted most recent first).
foo*(Lm+1) : files matching foo* whose size is at least 1MB.
foo*(N)  : same as foo*, but if this doesn't match any file, produce an empty list regardless of the setting of the null_glob option (see above).
*(D)     : match files including dot files (except . and ..).
foo/bar/*(:t) (using a history modifier) : the files in foo/bar, but with only the base name of the file. E.g. if there is a foo/bar/qux.txt, it's expanded as qux.txt.
foo/bar/*(.:r) : take regular files under foo/bar and remove the extension. E.g. foo/bar/qux.txt is expanded as foo/bar/qux.
foo*.odt(e\''REPLY=$REPLY:r.pdf'\') : files matching foo*.odt, and replace .odt by .pdf (regardless of whether the PDF file exists).


wildcard patterns.

foo*.txt~foobar*: .txt files whose name starts with foo but not foobar. image->.jpg(n): .jpg files whose base name is image followed by a number, e.g. image3.jpg and image22.jpg but not image-backup.jpg.
The glob qualifier (n) files in numerical order, i.e. image9.jpg comes before image10.jpg (you can make this the default even without -n with setopt numeric_glob_sort). To mass-rename files, zsh provides a very convenient tool: the zmv function. Suggested for your .zshrc: autoload zmv alias zcp='zmv -C' zln='zmv -L' Example: zmv '(*).jpeg' '$1.jpg' zmv '(*)-backup.(*)' 'backups/$1.$2' Bash has a few ways to apply transformations when taking the value of a variable. Zsh has some of the same and many more.

Change directories.
setopt auto_cd to change directory by entering only the sub-directory name
The two-argument form of cd changes to a directory whose name is close to the current directory. For example, From
/some/where/foo-old/deeply/nested/inside
to change directory to
/some/where/foo-new/deeply/nested/inside,
enter cd old new.

Don't use set to assign a value to a variable, use:

variable=value
To edit the value use vared variable.

Configuration interface including canned recipes for things like case-insensitive completion.

autoload -U zsh-newuser-install (A larget function)


zsh-newuser-install
Without a configuration file, many useful features are disabled for backward compatibility. zsh-newuser-install suggests some recommended features to turn on. Configuration frameworks on the web (many of them are on Github), can be a convenient way to get started with some powerful features.
However they often lock you in doing things the way the author does, so sometimes they'll prevent you from doing things the way you want. The manual has a lot of informatio, resources are the zsh-users mailing list and Unix Stack Exchange.
An extensive collection of articles on switching to zsh on the mac can be found on scriptingosx.com and a useful Ruby script to bring your command history with you, is on Github.

Does ctrl-o work on zsh. it doesn't work on Mac OS on bash C-o does the same thing in zsh with the default key bindings. fact that if the situation had been reversed, there wouldn't be a “nice bash features” section. Or it may be because the last non-GPLv3 bash is getting really old whereas zsh has a more

COMPATIBILITY

Emulates sh or ksh when invoked as sh or ksh.
Invoked as su uses the name from $SHELL and emulation is based on that.

Command history

With bash using vi esc k rettrieves the last command. And additional k retrieves the previous …. esc / searches the history for the text folling the slash.

Using zsh …

Comments

For non-interactive shells, or interactive shells with interactive_comments set, a word beginning with histchars[3](orgin 1!) (default # ) begins a comment which continues until the end-of-line .

With extended_glob (default set)
#   matchs zero or more of the pattern (corresponds to the regular expression modifier *)
## matchs one or more                          (corresponds to the regular expression modifier +).
If used intending to be a comment, zsh reports bad pattern!

Examples of treatment of #:

$ setopt extended_glob
$ echo hello # hello : hello  --- a history pattern match
zsh: bad pattern: #

$ unsetopt extended_glob
$ echo hello # hello : hello --- a regular character
hello # hello : hello

$ setopt interactive_comments
$ echo hello # hello : hello    --- a comment for the rest of the line.
hello

$ histchars[3]=:                --- changing  to use : as comment leading.
$ echo hello # hello : hello
hello # hello

bash interactive_comments  on by default in interactive shells.

$ echo hello # hello
hello
$ shopt -u interactive_comments   unset it
$ echo hello # hello
hello # hello


if [ -e .vimrc    bash true if .vimrc exists, zsh ...
if [ -a .vimrc    bash true if .vimrc exists, zsh [: too many arguments
if [ -d /Volume/DATA    bash true if /Volume/DATA exists, zsh false


zsh does not like $0 for the caller (depending on sourced script FUNCTION_ARGZERO ?? Both bash and zsh-compatible use ${BASH_SOURCE[0]:-${(%):-%x}} close but different %x ~= %N % is parameter expansion flag, see man zshexpn under the heading Parameter Expansion Flags. %x is one of the escape sequences that can be used in prompt strings see man zshmisc : SIMPLE PROMPT ESCAPES.

$x == 0 # Expected logical test to return result.
zsh: = not found

Zsh doesn't support the == operator within the [ ] test command, it interprets == as a command name .
Usei [[ ]]

$x=';' # Expected x to be assigned string value of ;
zsh: ; not found

Not even escaped with \. $x="x" # Expected x to be assigned string value of x .zprofile is executed !

alias desktop="cd desktop" < unmatched "

= expansion: =foo expands to the path to the foo !
zsh uses =cmd to expand to path of cmd. Ugly : "==" supresses the expansion
setopt noequals
Conditional-Expressions

When encounters:
set   editing-mode vi 
zsh reports  zsh:1: command not found: editing-mode


set |g vi
'*'=( editing-mode vi )
@=( editing-mode vi )
argv=( editing-mode vi )

set

'!'=0           also  echo $! reports  0
'#'=2
'$'=5982
'*'=( editing-mode vi )
-=569Xils
0=-zsh
'?'=127
@=( editing-mode vi )


zsh:  set |grep GROUP
bash: set |grep GROUP
      GROUPS=()


$SHELL=/bin/zsh
SHELL_SESSION_DID_HISTORY_CHECK=1
SHELL_SESSION_DID_INIT=1
SHELL_SESSION_HISTORY=1
SHELL_SESSION_DIR=/Users/$USER/.zsh_sessions
SHELL_SESSION_FILE=/Users/$USER/.zsh_sessions/C75FC5F8-92F5-4886-92D7-F2FB6FC7516D.session
                                    1/14/22 227 files since Dec 28, increasing in size fo 40KB to 100kb !
SHELL_SESSION_HISTFILE=/Users/$USER/.zsh_sessions/C75FC5F8-92F5-4886-92D7-F2FB6FC7516D.history
SHELL_SESSION_HISTFILE_NEW=/Users/$USER/.zsh_sessions/C75FC5F8-92F5-4886-92D7-F2FB6FC7516D.historynew    0 created at login(?)
SHELL_SESSION_HISTFILE_SHARED=/Users/$USER/.zsh_history
SHELL_SESSION_TIMESTAMP_FILE=/Users/$USER/.zsh_sessions/_expiration_check_timestamp
ZSH_SUBSHELL=1
The first two histchars (default ! ^ ) are used in history expansions.


--emulate mode can be used as the first option.
modes are described for the emulate builtin, see zshbuiltins.

When is compared with the emulate command : variables that conflict with POSIX usage such as path are not defined.

In sh and ksh compatibility modes :


Invoked as sh BSD_ECHO and IGNORE_BRACES are set.

Invoked as ksh KSH_OPTION_PRINT, LOCAL_OPTIONS, PROMPT_BANG, PROMPT_SUBST and SINGLE_LINE_ZLE are set.

builtin commands NOT in bash

autoload [ {+|-}UXktz ] [ -w ] [ name]

Equivalent to functions -u, with the exception of -X/+X and -w.
-X may be used only inside a shell function, and may not be followed by a name, causes the calling function to be marked for autoloading and then immediately loaded and executed, with the current array of positional parameters as arguments. This replaces the previous definition of the function.
If no function definition is found, an error is printed and the function remains undefined and marked for autoloading.
+X loads each name as an autoloaded function, but does not execute it.
The exit status is zero (success) if the function was not previously defined and a definition for it was found.
This does not replace any existing definition of the function.
The exit status is nonzero (failure) if the function was already defined or when no definition was found. In the latter case the function remains undefined and marked for autoloading.
If ksh-style autoloading is enabled, the function created will contain the contents of the file plus a call to the function itself appended to it, giving normal ksh autoloading behaviour on the first call to the function.

With -w files are compiled with zcompile builtin and functions defined in them are marked for autoloading.

-z and -k mark the function to be autoloaded in native or ksh emulation, as if KSH_AUTOLOAD were unset or were set, respectively. The flags override the setting of the option at the time the function is loaded.

STARTUP/SHUTDOWN FILES

If $ZDOTDIR is unset $HOME is used .

At startup

  1. /etc/zshenv Commands are read, this cannot be overridden.
      Apple mac os, none is present

    Run for all instances of zsh and should be as small as possible. Code that does not need to be run for every shell should be behind a test of the form if [[ -o rcs ]]; then … so that it will not be executed when zsh is invoked with -f.

    RCS (set by default) if unset supresses processing of subsequent startup files.
    GLOBAL_RCS (set by default) if unset supresses processing of subsequent global startup files (those shown here with an path starting with a /).
    A file in $ZDOTDIR can re-enable GLOBAL_RCS.

  2. $ZDOTDIR/.zshenv
  3. /etc/zprofile
      Apple mac os has
    • if [ -x /usr/libexec/path_helper ]; then
      eval `/usr/libexec/path_helper -s`
  4. $ZDOTDIR/.zprofile for a login shell, $ZDOTDIR/.zshrc for interactive.
      Apple mac os for /etc/zshrc has :
    • disable log
    • HISTFILE=${ZDOTDIR:-$HOME}/.zsh_history # Save command history
    • HISTSIZE=2000
    • SAVEHIST=1000
    • setopt BEEP # Beep on error
    • PS1="%n@%m %1~ %# " # prompt uname @ host %
    • PS1="%m %1~ %# " # without uname
    • many key bindings there
      zshrc_Apple_Terminal
    • Tell the terminal about the current working directory at each prompt.
    • big hairy stuff
  5. /etc/zlogin
  6. $ZDOTDIR/.zlogin for a login shell

When the login shell exits:

  1. $ZDOTDIR/.zlogout
  2. /etc/zlogout are processed unless the shell terminates due to exec'ing another process
These are affected by $RCS and $GLOBAL_RCS .
If $RCS is unset no history file will be saved.

Compiled files newer than the original will be used (see zshbuiltin zcompile).

FILES

       $ZDOTDIR/.zshenv
       $ZDOTDIR/.zprofile
       $ZDOTDIR/.zshrc
       $ZDOTDIR/.zlogin
       $ZDOTDIR/.zlogout
       ${TMPPREFIX}*   (default is /tmp/zsh*)
       /etc/zshenv
       /etc/zprofile
       /etc/zshrc
       /etc/zlogin
       /etc/zlogout    (installation-specific - /etc is the default)

SEE ALSO sh(1), csh(1), tcsh(1), rc(1), bash(1), ksh(1), zshall(1), zshbuiltins(1), zshcompwid(1), zshcompsys(1), zshcompctl(1), zshcontrib(1), zshexpn(1), zshmisc(1), zshmodules(1), zshoptions(1), zshparam(1), zshroadmap(1), zshtcpsys(1), zshzftpsys(1), zshzle(1)

A user guide is at http://zsh.sourceforge.net/Guide/. At


13.1 Expansion of Prompt Sequences

Prompt-Expansion.html

Prompt sequences undergo a special form of expansion, which is also available using print -P builtin.

With $PROMPT_SUBST set the prompt string is substuted via parameter , command and arithmetic expansion.

With $PROMPT_BANG set, a ! displays the current history event number. Use !! to display a !.

With $PROMPT_PERCENT set, escape sequences starting with % are expanded.
Many escapes are followed by a single character, some take an optional integer argument between the '%' and the next character of the sequence.
More complicated escape sequences are available to provide conditional expansion.

13.2 Simple Prompt Escapes

Zsh version 5.9, released on May 14, 2022.


Apple does things a little differently .

13.2.1 Special characters
%% A '%'.
%) A ')'.
13.2.2 Login information
%l tty logged in on
%y tty logged in on,does not treat '/dev/tty' names specially.
%M Machine hostname
%[c]m number of components of the hostname are desired. With a negative integer, trailing components of the hostname are shown.
%n $USERNAME.
13.2.3 Shell state
%# running with privileges:# ; if not % .
Equivalent to '%(!.#.%%)'. 'privileged',the effective user ID is zero, or,
WIth POSIX.1e capabilities , at least one capability is raised in either the Effective or Inheritable capability vectors.
%? return status $? of the last command
%_ The status of the parser, i.e. the shell constructs (like 'if' and 'for') that have been started on the command line. If given an integer number that many strings will be output; 0 or negative or no integer means output as many as there are.
Useful in prompts PS2 for continuation lines and PS4 for debugging with XTRACE ; works non-interactively.
%^ The status of the parser in reverse. This is the same as '%_' other than the order of strings. It is often used in RPS2.
%[c]d
%[c]/
Current working directory. c number of trailing components
0 means the whole path.
A negative integer specifies leading components, i.e. %-1d specifies the first component.
%~ $HOME is replaced by ~,
for %d and %/, A named directory (example /~tony ?) is replaced by a '~' and the name of the directory, if the result is shorter than the full path; Filename Expansion.
%c
%.
%C
Trailing component of the CWD. An integer may follow the '%' to get more than one component.
Unless '%C' is used, tilde contraction is performed first. These are deprecated as %c and %C are equivalent to %1~ and %1/, respectively, while explicit positive integers have the same effect as for the latter two sequences.
 
%[c]N most reccently started script, sourced file, or shell function currently executing, .
If there is none, this is equivalent to the parameter $0.
An integer follow the % specifes a number of trailing path components to show
0 means the full path.
A negative integer specifies leading components.
%I line number currently being executed in the file %x. This is similar to %i, but the line number is always a line number in the file where the code was defined, even if the code is a shell function.
%j, Number of jobs.
%L $SHLVL
%h
%!
Current history event number.

13.2.4 Date and time

%D yy-mm-dd
%T 24:mm | %K 0..24 | %L 0..12
%t
%@
12-hour, am/pm
%* 24-hour format, with seconds.
%w day-dd
%W mm/dd/yy .
%D{string} string format using the strftime function. See strftime(3) . Various zsh extensions provide numbers with no leading zero or space if the number is a single digit:
%f mm %. decimal fractions of a second since the epoch with leading zeroes.
default seconds, %6. microseconds, and %9. nanoseconds.date does not support these
%D{%H:%M:%S.%.}.
%N synonym for %9.. A - between the % and the format character causes a leading zero or space to be stripped is handled directly by the shell for the format characters d, f, H, k, l, m, M, S and y.
Other format characters are processed by strftime(3) with any leading '-' present,
%i line number being executed in the script, sourced file, or shell function given by %N. Useful for debugging as part of $PS4.
%x File containing the currently being executed.
as %N except that function: and eval the file where they were defined,command names are not shown.
%e depth of the current sourced file, shell function, or eval, incremented or decremented every time the value of %N is set or reverted to a previous value. Useful for debugging as part of $PS4.
The following seem a little too fancy
13.2.5 Visual effects
%E Clear to end of line.
%B (%b) Start (stop) bold
%S (%s) Start (stop) standout mode.
%U (%u) Start (stop) underline mode
%F (%f) Start (stop) foreground color as a numeric argument, as normal OR
by a sequence in braces following %F, for example %F{red}. the values allowed are as described for the fg zle_highlight attribute; Character Highlighting. This means that numeric colours are allowed in the second format also.
%K (%k) backGround color
%{...%} Include a string as a literal escape sequence. must not change the cursor position. Brace pairs can nest.
A positive numeric argument between the % and the { is treated as described for %G
%G Within a %{...%} sequence, include a glitch: that is, a single character which will be output.
Useful when outputting characters that cannot be correctly handled by the shell, such as the alternate character set on some terminals.
The characters in question can be included within a %{...%} sequence together with the appropriate number of %G sequences to indicate the correct width.
An integer between the % and G indicates a character width other than one.
To output seq and have it takes up the width of two characters. %{seq%2G%}
Multiple uses of %G accumulate in the obvious fashion; the position of the %G is unimportant.
Negative integers are not handled.
When prompt truncation is in use it is advisable to divide up output into single characters within each %{...%} group so that the correct truncation point can be found.
13.3 Conditional Substrings in Prompts
%v First element of the psvar array parameter. Following the '%' with an integer gives that element of the array. Negative integers count from the end of the array.
%(test.
true-text.
false-text
)
To include the separator int the true-test use a %-escape sequence.
To include a ')' in the false-text use '%)'.
true-text and false-text may both contain arbitrarily-nested escape sequences, including further ternary expressions.
The left parenthesis may be preceded or followed by a positive integer n, which defaults to 0. A negative integer will be multiplied by -1, except as noted below for 'l'. The test x may be any of the following:
True if …
! privileges.
# effective uid of the current process is n.
? exit status of the last command was n.
_ True if at least n shell constructs were started.
C / True if the current absolute path has at least n elements relative to the root directory, / is counted as 0 elements.
c . ~ True if the current path, with prefix replacement, has at least n elements relative to the root directory, hence / is counted as 0 elements.
D the month is equal to n (January = 0).
d if the day of the month is equal to n.
e the evaluation depth is at least n.
g the effective gid of the current process is n.
j the number of jobs is at least n.
L $SHLVL is at least n.
l at least n characters have already been outptu on the current line.
When n is negative, true if at least abs(n) characters remain before the opposite margin (thus the left margin for RPROMPT).
S if the SECONDS parameter is at least n.
T hours is equal to n.
t minutes is equal to n.
v array psvar has at least n elements.
V element n of psvar is set and non-empty.
w day of the week is n (Sunday = 0).

%<string>
%<string>
%[xstring]

Truncation behaviour for the remainder of the prompt string.
The third, deprecated, form is equivalent to '%xstringx', i.e. x may be '<' or '>'.
The string will be displayed in place of the truncated portion of any string; note this does not undergo prompt expansion.

The numeric argument, which in the third form may appear immediately after the '[', specifies the maximum permitted length of the various strings that can be displayed in the prompt.
In the first two forms, this numeric argument may be negative, in which case the truncation length is determined by subtracting the absolute value of the numeric argument from the number of character positions remaining on the current prompt line. If this results in a zero or negative length, a length of 1 is used. In other words, a negative argument arranges that after truncation at least n characters remain before the right margin (left margin for RPROMPT).

The forms with '<' truncate at the left of the string, and the forms with '>' truncate at the right of the string.
For example, if the current directory is /home/pike, the prompt %8<..<%/ will expand to ..e/pike.
In this string, the terminating character ('<', '>' or ']'), or any character, may be quoted by a preceding '\'; .
When using print -P that this must be doubled as the string is also subject to standard print processing,
any backslashes removed by a double quoted string: the worst case is therefore 'print -P "%<\\\\<<..."'.

If the string is longer than the specified truncation length, it will appear in full, completely replacing the truncated string.

The part of the prompt string to be truncated runs to the end of the string, or to the end of the next enclosing group of the '%(' construct, or to the next truncation encountered at the same grouping level (i.e. truncations inside a '%(' are separate), which ever comes first.
A truncation with argument zero (e.g., '%<<') marks the end of the range of the string to be truncated while turning off truncation from there on. For example, the prompt '%10...<%~%<<%# ' will print a truncated representation of the current directory, followed by a '%' or '#', followed by a space. Without the '%<<', those two characters would be included in the string to be truncated. Note that '%-0<<' is not equivalent to '%<<' but specifies that the prompt is truncated at the right margin.

Truncation applies only within each individual line of the prompt, as delimited by embedded newlines (if any).
If the length of any line of the prompt is greater than the terminal width, or if the part to be truncated contains embedded newlines, truncation behavior is undefined Use '%-n(l.true-text.false-text)' to remove parts of the prompt when the available space is less than n.