Zsh Cheatsheet - Config, Aliases, Glob & Completion

After switching the default shell, the speedup does not come from syntax — it comes from smarter completion, prefix-aware history search, and a prompt that doubles as a status display. The sheet is organised around the seven parts of .zshrc people keep editing: base options, variables and arrays, globbing and expansion, history, functions and completion, prompt customisation, and oh-my-zsh with plugins. A few gotchas are called out: zsh arrays index from 1 while bash arrays index from 0, which is the most common source of breakage when porting scripts. setopt AUTO_CD lets you hit enter on a directory name, and pairs with AUTO_PUSHD to turn cd - into a jump list. EXTENDED_GLOB is what makes ** genuinely recursive rather than one level deep. Binding the arrow keys to history-search-backward turns them from a time scrollbar into a prefix search over past commands. On oh-my-zsh, remember it adds measurable startup cost, so cherry-pick plugins on production boxes.

SysOps·37 commands·Last updated 2026-07-21
zshshellTerminaloh-my-zsh

Typical Use Case

For developers who have just moved their default shell to zsh: make completion, history search, aliases and the prompt actually do the work. What zsh adds over bash concentrates in three places — recursive globbing (**), copyable history search (Ctrl+R), and glob qualifiers such as *(om[1]) to pick the newest file. This sheet covers the high-traffic .zshrc options and oh-my-zsh plugin usage; best read once in the first week after switching, then revisit as needed.

Basic Setup 5

chsh -s $(which zsh)
Switch the default shell to zsh
source ~/.zshrc
Reload the config
echo $SHELL
Show the current shell
setopt AUTO_CD
Type a dir name to cd (no cd needed)
setopt CORRECT
Suggest corrections on typo

Variables & Arrays 6

NAME="value"
Define a variable (no spaces around =)
arr=(a b c)
Define an array (zsh indexes from 1)
echo $arr[1]
Access the first array element
echo ${arr[@]}
Access all array elements
${#arr[@]}
Get array length
typeset -A dict\ndict[key]=value
Define an associative array (hash)

Globbing & Expansion 6

**/*.js
Recursively match .js in subdirs
*.{js,ts}
Brace expansion, multiple suffixes
*(.)
Match regular files only (glob qualifier)
*(/)
Match directories only
*(om[1])
The most recently modified file
=ls
= expands to the command's full path

Functions & Completion 4

function name() { ... }
Define a function
alias ll="ls -la"
Set an alias
autoload -Uz compinit && compinit
Initialize the completion system
compdef _git g=git
Reuse git completion for alias g

Prompt Customization 5

PROMPT='%n@%m %~ %# '
user@host path prompt
%n / %m / %M
username / short host / full host
%~ / %d
current dir (~) / absolute path
RPROMPT="%T"
Right prompt shows current time
%T / %D / %W
24h time / date / month-day-year

oh-my-zsh & Plugins 5

plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
Enable a plugin list
ZSH_THEME="robbyrussell"
Set a theme (random to rotate)
zsh-autosuggestions
Autosuggest completions (accept with ->)
zsh-syntax-highlighting
Syntax highlighting (red = error)
extract file.tar.gz
extract plugin auto-detects archive format

Parameter matrix

ParameterEffectExample
setopt AUTO_CD输入目录名即进入,无需写 cdsetopt AUTO_CD
setopt CORRECT命令拼错时提示纠正setopt CORRECT
HISTSIZE / SAVEHIST内存与文件的历史条数,两者都设才生效HISTSIZE=10000; SAVEHIST=10000
setopt SHARE_HISTORY多终端实时共享历史记录setopt SHARE_HISTORY
Ctrl+R反向增量搜索历史命令Ctrl+R 后输入 git 关键词
!!执行上一条命令,sudo !! 是经典组合sudo !!
!$上一条命令的最后一个参数mkdir -p /var/log/app; cd !$
**/*.js递归匹配所有层级的 .js 文件ls **/*.js
*.{js,ts}花括号扩展,一次匹配多种后缀ls *.{js,ts}
*(om[1])glob 限定符:取最近修改的一个文件ls -t *(om[1])
compdef _git g为别名 g 复用 git 的补全compdef _git g=git
%~ / %n / %T提示符占位符:当前目录 / 用户名 / 时间PROMPT='%n@%m %~ %# '

Common pitfalls

Symptom脚本从 bash 换到 zsh 后数组取值全为空,${arr[0]} 拿不到第一个元素。

Causezsh 数组默认从下标 1 开始,而 bash 从 0 开始。

Fix改用 ${arr[1]},或执行 emulate sh / setopt KSH_ARRAYS 让行为贴近 bash。

Symptom在 .zshrc 里定义了 alias 后,同一行继续用该别名没有生效。

Causealias 在同一次读取中只对其后的命令生效。

Fix把 alias 单独放一行,或改用函数 function name() { ... }。

Symptom装上 zsh-syntax-highlighting 后命令高亮不工作或报错。

Cause插件加载顺序不对,highlighter 必须在 plugins 数组最后加载。

Fix写 plugins=(git zsh-autosuggestions zsh-syntax-highlighting),把 highlighter 放到末尾。

Symptom切到 zsh 后进不去交互 shell,只能走 sh 兜底。

Cause~/.zshrc 存在语法错误,启动时解析中断。

Fix用 zsh -n ~/.zshrc 做语法检查(只解析不执行),定位到错误行先注释掉。

Symptomzsh-autosuggestions 的灰色建议按方向键不接受。

Cause默认接受键是 →(右方向键),按 End 或空格无效。

Fix按 → 接受整条建议;只接受单词需额外配置。

SymptomCtrl+R 搜到的命令执行后发现参数不对,但历史里只有这一条。

Cause历史中未保存该命令的变体。

Fix提高历史条数:HISTSIZE=10000 SAVEHIST=10000,并用 history -i | tail 看带时间戳的历史。

Troubleshooting

  1. 1确认当前 shell 与配置是否生效

    echo $SHELL && zsh -n ~/.zshrc

    前者看登录 shell,后者只做语法检查(-n),能定位 .zshrc 的解析错误。

  2. 2改完配置立即重载

    source ~/.zshrc

    每次改 .zshrc 后执行一次;可写成 alias reload-cfg="source ~/.zshrc" 省事。

  3. 3递归查找任意层级的 .js 文件

    ls **/*.js

    ** 是 zsh 的递归通配;bash 需先开启 globstar(shopt -s globstar)。

  4. 4取出最近修改的那个日志文件

    ls -t *(om[1])

    (om[1]) 是 glob 限定符,o 按修改时间排序取第 1 个;bash 需 find + printf。

  5. 5在历史里搜含关键字的命令并直接执行

    git rebase

    输入前缀后按 Ctrl+R 向上检索,回车执行;配 SHARE_HISTORY 多终端实时共享。

Command Examples

Recall a matching command from history

git rebase

直接在终端输入 git rebase 再按 Ctrl+R,会向上检索含该前缀的历史,方向键或 Enter 直接执行。配 setopt SHARE_HISTORY 多终端历史实时共享。

Reuse the last argument of the previous command

mkdir -p /var/log/myapp cd !$

!$ 展开为上一条命令的最后一个参数,!^ 是第一个,!! 是整条。sudo !! 是最经典的组合——先执行一条危险命令,再用同样的参数加 sudo 重跑。

Recursively match files at any depth

ls **/*.ts ls *(om[1]).log

** 递归匹配所有层级(bash 需开启 globstar);*(om[1]) 是 glob 限定符,取最近修改的一个 .log 文件。bash 要用 find 配合 -printf 才能做到。

Output

src/index.ts
src/api/client.ts
src/api/auth/login.ts

Reload the config immediately

source ~/.zshrc

每次改动后执行一次;写成 alias reload-cfg="source ~/.zshrc" 更方便。注意 alias 在同一个文件里定义后不会作用于该行本身。

Common Pitfalls

  • zsh arrays are 1-indexed, so ${arr[0]} is empty — the most common porting trap from bash.
  • An alias only takes effect on subsequent lines; defining and using it on the same line does nothing.
  • Plugin order matters: zsh-syntax-highlighting must be loaded last in the plugins array.
  • ${arr[@]} expands differently in zsh than bash, so quote it explicitly in portable scripts.
  • Verify ~/.zshrc parses before switching your login shell — one syntax error can leave you without a working interactive prompt.

Tips

  • Install oh-my-zsh: sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
  • zsh-autosuggestions needs a separate install (git clone into $ZSH_CUSTOM/plugins).
  • setopt AUTO_CD lets you cd by typing a dir name.
  • Bind up/down arrows to prefix history search via bindkey.
  • zsh arrays start at 1 (bash starts at 0) - mind this when porting scripts.
  • ZDOTDIR changes the config dir, handy for isolated configs.

FAQ

Do zsh arrays start at index 0 or 1?

zsh indexes arrays from 1, while bash starts at 0. This is one of the most common porting traps: in zsh ${arr[0]} is an empty element, not the first one, and the correct form is ${arr[1]}. To make zsh behave more bash-like, use emulate sh or setopt KSH_ARRAYS.

Beyond Ctrl+R, what history tricks does zsh offer?

Ctrl+R does reverse incremental search, and pressing it again walks further back. Beyond that: !! repeats the previous command, making sudo !! the classic pairing; !$ expands to the last argument of the previous command, so after mkdir -p /var/log/app, cd !$ lands you there; !^ grabs the first argument. And setopt SHARE_HISTORY shares history live across terminal windows.

Where is zsh globbing stronger than bash?

Three main things. ** recurses into subdirectories, which bash needs globstar for. Brace expansion *.{js,ts} matches several extensions in one pattern instead of listing them. And glob qualifiers let you filter: *(.) regular files only, *(/) directories only, *(om[1]) the single most recently modified one. In bash you would need find for equivalent filtering.

How do I set up syntax highlighting and autosuggestions in zsh?

Two plugins do it: zsh-syntax-highlighting highlights command syntax live (invalid commands turn red) and zsh-autosuggestions shows a grey inline suggestion from your history that you accept with the right arrow. Add plugins=(git zsh-autosuggestions zsh-syntax-highlighting) to .zshrc and enable the completion system with compinit. Make sure the highlighter is loaded last in the plugins array.

What do %~, %n and %T mean in the zsh prompt?

%n is the username, %m the short hostname, %M the full hostname. %~ is the current path with the home directory abbreviated to ~, while %d prints the absolute path. %T is the time in 24-hour form, %D the year-month-day, %W the month-day-year. The classic PROMPT='%n@%m %~ %# ' shows user@host path plus a prompt char, where %# renders as $ for a normal user and # for root.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us