Cheat sheets Zsh

Zsh cheat sheet: startup files, options, history, globbing, and expansion

Zsh is an interactive shell and scripting language. Much of what sets it apart is opt-in: options you turn on, glob qualifiers you learn, and a few builtins that bash doesn’t have. This sheet covers where config goes, a starter set of options, history shortcuts, globbing, expansion modifiers, and the differences from bash that catch people out. Everything below is from the official Zsh manual, version 5.9.2. We attempt to test on all versions.

what it is and when to use it

Use zsh as your login shell if you live in a terminal and want stronger globbing, history, and completion than a plain POSIX shell. Scripts meant to run anywhere should still say #!/bin/sh and avoid zsh-only syntax. Zsh’s default mode is not POSIX compatible.

check the version

CommandWhat it does
zsh --version
From any shell
echo $ZSH_VERSION
From inside zsh
zsh -f
Start a zsh that skips your startup files, to test whether your config causes a problem

startup files

zsh reads these in order. Each user file lives in $ZDOTDIR, or in your home directory if ZDOTDIR is unset.

FileWhat it does
.zshenvEvery zsh, including scripts. Keep it small.
.zprofileLogin shells only.
.zshrcInteractive shells. Aliases, options, prompt, and key bindings go here.
.zloginLogin shells, after .zshrc.
.zlogoutWhen a login shell exits.

The system files in /etc (/etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin, /etc/zlogout) run before or after each user file. /etc/zshenv always runs first. On some systems those files live in a different directory.

CommandWhat it does
source ~/.zshrc
Reread .zshrc in the current shell
exec zsh
Replace the current shell with a fresh one

options

Option names ignore case and underscores, so AUTO_CD, autocd, and auto_cd are the same option. Put no in front to turn one off: setopt no_beep is the same as unsetopt beep.

CommandWhat it does
setopt
List the options that are on
unsetopt
List the options that are off

Common choices for ~/.zshrc:

~/.zshrc
setopt auto_cd
setopt auto_pushd
setopt pushd_ignore_dups
setopt extended_glob
setopt hist_ignore_dups
setopt hist_ignore_space
setopt interactive_comments
OptionWhat it does
auto_cdType a directory name on its own to cd into it.
auto_pushdEvery cd pushes the old directory onto the stack (see dirs -v below).
pushd_ignore_dupsDon’t push the same directory twice.
extended_globTurn on the ^, ~, and # glob operators.
hist_ignore_dupsDon’t save a command that repeats the previous one.
hist_ignore_spaceDon’t save a command that starts with a space. Use it for one-off commands with secrets in them.
interactive_commentsAllow # comments at the prompt.

history

History needs three variables. If HISTFILE is unset, history is not saved at all.

~/.zshrc
HISTFILE=~/.zsh_history
HISTSIZE=50000
SAVEHIST=50000
SettingWhat it does
HISTSIZEHow many events the shell keeps in memory.
SAVEHISTHow many events are saved to the file.
share_historyEach shell writes commands to the file as you run them and reads in commands from other shells.
inc_append_historyWrite each command to the file as you run it, without importing other shells' commands.

The manual says share_history, inc_append_history, and inc_append_history_time should be treated as mutually exclusive. Pick one.

CommandWhat it does
history -10
The last 10 history entries

History expansion at the prompt:

ShortcutWhat it does
!!The previous command. sudo !! reruns it with sudo.
!$The last argument of the previous command.
!*All arguments of the previous command.
!-2The command before the previous one.
!gitThe most recent command that starts with git.
^foo^barRerun the previous command with the first foo replaced by bar.
Ctrl-RSearch history incrementally, in the emacs keymap (the default unless EDITOR or VISUAL contains vi).

globbing

CommandWhat it does
print -l **/*.md
Every .md file in this directory and all subdirectories

Glob qualifiers go in parentheses at the end of a pattern:

PatternWhat it does
*(.)Plain files only.
*(/)Directories only.
*(@)Symbolic links only.
*(N)Expand to nothing instead of failing when there are no matches.
*(D)Include dotfiles.
*(om[1,3])The three most recently modified.
*(Lm+100)Larger than 100 megabytes.
*(mh-1)Modified within the last hour. mw-1 is within the last week.
CommandWhat it does
ls -l *.log(om[1,3])
The three newest log files
print -l **/*(.Lm+100)
Files over 100 MB anywhere under the current directory

With extended_glob set:

PatternWhat it does
^*.mdEverything except .md files.
*.txt~notes.txtEvery .txt file except notes.txt.

Without it:

PatternWhat it does
(foo|bar).txtfoo.txt or bar.txt.
log<1-10>.txtlog1.txt through log10.txt.

expansion and modifiers

Modifiers work on variables, on history references, and on glob results.

f=/var/log/nginx/access.log.gz
echo ${f:h}
echo ${f:t}
echo ${f:r}
echo ${f:e}
output
/var/log/nginx
access.log.gz
/var/log/nginx/access.log
gz
ModifierWhat it does
:hHead, the directory part.
:tTail, the file name.
:rRoot, without the last extension.
:eThe last extension only.
:aAn absolute path, worked out without touching the filesystem.
:ALike :a, then resolves symbolic links.
CommandWhat it does
name=sysop
echo ${(U)name} ${(L)name} ${#name} ${missing:-fallback}
Upper case, lower case, length, and a default value
arr=(alpha beta gamma)
echo $arr[1] ${#arr}
output
alpha 3
Arrays start at 1, not 0

directories

CommandWhat it does
dirs -v
Numbered directory stack (fills up when auto_pushd is on)
cd ~2
Jump to entry 2 on the stack
cd -
Go back to the previous directory
cd 2025 2026
Two-argument cd: swap one string in the current path for another

The second form turns /srv/reports/2025/q4 into /srv/reports/2026/q4 and changes to it.

builtins worth knowing

CommandWhat it does
autoload -Uz zmv
Bulk-rename with a pattern: load zmv first
zmv -n '(*).txt' '$1.md'
Preview the rename with -n
zmv '(*).txt' '$1.md'
Then run it without -n
autoload -Uz compinit && compinit
Turn on the completion system
bindkey -e
Emacs keys on the command line
bindkey -v
Vi keys on the command line
whence -v ls
How a command name would be interpreted: alias, function, builtin, or file
alias -g G='| grep'
Global alias: expands anywhere on the line, not just as the command
alias -s md=glow
Suffix alias: typing a file name ending in .md opens it with glow
rehash
Forget remembered command locations after installing something new
print -l $path
Print each argument on its own line: here, each directory in PATH

gotchas

  • Unquoted $var is not split on spaces the way it is in bash. That only happens with the sh_word_split option set. Arrays are the zsh way to hold a list.
  • Arrays are 1-indexed unless ksh_arrays is set.
  • A glob with no matches is an error (no matches found), not passed through as literal text. This is the nomatch option, on by default. Add (N) to a pattern that may match nothing. Quote URLs and other arguments that contain ?, *, or [.
  • .zshenv runs for every zsh, including scripts and zsh -c. Anything that prints output or is slow belongs in .zshrc.
  • zmv stops without doing anything if two files would end up with the same name, or if a target already exists and you didn’t give -f. Always run zmv -n first anyway.
  • alias -g and alias -s are powerful and easy to forget. A global alias named G changes any command line that has G as a separate word.

sources

Checked against the Zsh manual, version 5.9.2 (released July 12, 2026), on zsh.sourceforge.io. Older versions: man zshall on your own machine.