跳至內容

Zsh

出自 Arch Linux 中文维基

Zsh 是一款功能強大的命令行解釋器(shell),既可以作為交互式終端來使用,也可以作為腳本語言解釋器來使用。它在兼容 POSIX 的 sh 的同時(默認不兼容,僅在使用 emulate sh 時兼容),還改進了 Tab 補全通配符等功能。

Zsh FAQ 說明了使用 Zsh 的更多原因。

安裝[編輯 | 編輯原始碼]

在開始安裝之前,可以查看一下當前正在使用的 Shell 軟件:

$ echo $SHELL

安裝 zsh 包,也可以同時安裝 zsh-completions 包以獲取更多命令補全規則。

初始配置[編輯 | 編輯原始碼]

在終端裡面輸入以下命令,確保已經正確安裝了 Zsh:

$ zsh

運行後你應該會看到zsh-newuser-install(新用戶安裝嚮導),它可以協助你完成一些基礎配置。如果要跳過這一步驟,可以按 q 退出。如果你沒有看到zsh-newuser-install,可以手動運行以下命令:

$ autoload -Uz zsh-newuser-install
$ zsh-newuser-install -f
注意:確保你的終端尺寸至少為 72×15 大小,否則zsh-newuser-install將無法運行。

將 Zsh 設為默認 Shell 軟件[編輯 | 編輯原始碼]

將 Shell 改為 /usr/bin/zsh。參見命令行解釋器#更改默認_Shell

提示:如果要替換 bash,用戶可能希望能夠將 ~/.bashrc 文件的某些代碼轉移到 ~/.zshrc 文件(例如:命令提示符和別名),以及將 ~/.bash_profile 文件的代碼轉移到 ~/.zprofile 文件(例如:啟動 X Window System 的代碼)。

啟動/關閉文件[編輯 | 編輯原始碼]

提示:有關交互式 shell 和登錄 shell 的解釋以及在啟動文件中放置內容的建議,請參閱 A User's Guide to the Z-Shell(Z-Shell 用戶指南,英文)。
注意:
  • 如果未設置$ZDOTDIR,則使用$HOME
  • 如果在任何文件中取消設置RCS選項,那麼之後的配置文件將不會被讀取。
  • 如果在任何文件中取消設置GLOBAL_RCS選項,那麼之後的全局配置文件(/etc/zsh/*)將不會被讀取。

在啟動時,Zsh 會按以下順序讀取這些文件(如果存在):


  • /etc/zsh/zshenv 用於設置所有用戶的環境變量。不應包含會產生輸出或假設 shell 連接到 TTY 的命令。此文件一旦存在就會被讀取,且無法跳過。
  • $ZDOTDIR/.zshenv 用於設置用戶的環境變量。不應包含會產生輸出或假設 shell 連接到 TTY 的命令。此文件一旦存在就會被讀取。
  • /etc/zsh/zprofile 在啟動為登錄 shell 時為所有用戶執行的命令。在 Arch Linux 中,此文件默認包含一行引入/etc/profile的代碼。在刪除該行之前,請參閱下方的警告!
    • /etc/profile 此文件應由所有符合 POSIX 標準的 shell 在登錄時引入,用於設置$PATH及其他環境變量,以及應用程序相關的設置(/etc/profile.d/*.sh)。
  • $ZDOTDIR/.zprofile 在啟動為登錄 shell 時執行的用戶命令。通常用於自動啟動圖形會話和設置會話範圍的環境變量。
  • /etc/zsh/zshrc 用於為所有用戶設置交互式 shell 的配置並執行命令,會在啟動為交互式 shell 時讀取。
  • $ZDOTDIR/.zshrc 用於為用戶設置交互式 shell 配置並執行命令,會在啟動為交互式 shell 時讀取。
  • /etc/zsh/zlogin 在初始進程結束時為所有用戶執行的命令,會在啟動為登錄 shell 時讀取。
  • $ZDOTDIR/.zlogin 在初始進程結束時執行的用戶命令,會在啟動為登錄 shell 時讀取。通常用於自動啟動命令行工具,不應用於啟動圖形會話,因為此時會話可能包含僅適用於交互式 shell 的配置。
  • $ZDOTDIR/.zlogout登錄 shell 退出時執行的用戶命令。
  • /etc/zsh/zlogout登錄 shell 退出時為所有用戶執行的命令。

請參閱圖示說明(英文)

注意:$HOME/.profile不是Zsh的啟動文件的一部分,除非 zsh 以shksh模式運行並作為登錄 shell 啟動,否則不會被 zsh 引入。有關 sh 和 ksh英語ksh 兼容模式的更多詳情,請參閱zsh(1) § COMPATIBILITY
警告:不要刪除/etc/zsh/zprofile中的默認代碼,否則會破壞某些在/etc/profile.d/目錄下提供腳本的軟件包的完整性。

配置 Zsh[編輯 | 編輯原始碼]

儘管 Zsh 開箱即用,但它的默認設置不符合大多數用戶的使用習慣。但由於 Zsh 有着大量自定義選項,配置 Zsh 可能是一項艱巨而耗時的體驗。有關自動配置,請參閱#第三方擴展

簡單的 .zshrc[編輯 | 編輯原始碼]

下面是一個示例配置文件。它提供了一組不錯的默認選項,並給出了許多可以自定義 Zsh 的方法的示例。要使用此配置,請將其保存為 .zshrc

提示:運行 source ~/.zshrc 可立即應用更改,無需註銷後重新登錄。
~/.zshrc
autoload -Uz compinit promptinit
compinit
promptinit

# 將默認命令行提示設置為 walters 主題
prompt walters

有關命令提示主題系統的更多詳細信息,請參閱#提示主題

配置 $PATH[編輯 | 編輯原始碼]

Zsh 將 PATH 變量綁定到 path 數組。這樣,您只需修改 path 數組即可操作 PATH。有關詳細信息,請參閱 A User's Guide to the Z-Shell(Z-Shell 用戶指南,英文)。

PATH變量中添加~/.local/bin/

~/.zshenv
typeset -U path PATH
path=(~/.local/bin $path)
export PATH

命令補全[編輯 | 編輯原始碼]

也許 Zsh 最引人注目的特性就是它先進的自動補全功能。至少,請在 .zshrc 中啟用自動完成功能。在 ~/.zshrc 的最後加入下面的配置開啟自動補全:

~/.zshrc
autoload -U compinit
compinit

上面的補全配置包括 ssh/scp/sftp 命令中的主機名補全。但是要讓這個特性正常工作,不能啟用 ssh 的主機名散列(hash,即 ssh 客戶端配置中的 HashKnownHosts 選項)。

添加下面的配置可以啟動使用方向鍵控制的自動補全:

~/.zshrc
zstyle ':completion:*' menu select

按兩次 Tab 啟動菜單

為了實現在特權命令中(例如,當你以 sudo 開始輸入一個命令時,補全腳本也會嘗試確定你可以用 sudo 完成的選項)對特權環境的自動補全,添加:

~/.zshrc
zstyle ':completion::complete:*' gain-privileges 1
警告:這允許 Zsh 補全腳本以 sudo 權限運行命令。如果您使用不受信任的自動補全腳本,則不應啟用此功能。
注意:這種特殊的上下文感知補全僅適用於少數命令。

自定義補全[編輯 | 編輯原始碼]

可以自己編寫自定義補全,參考 zshcompsys(1) 手冊頁。

請注意,官方文檔可能難以閱讀,可以考慮嘗試更簡單的 zsh-completion-howto 教程(英文),以便輕鬆入門。

消除歷史記錄中的重複條目[編輯 | 編輯原始碼]

~/.zshrc
setopt HIST_IGNORE_DUPS

假如目前的歷史記錄中已經有重複條目,可以運行下面的命令清除

$ sort -t ";" -k 2 -u ~/.zsh_history | sort -o ~/.zsh_history

快捷鍵綁定[編輯 | 編輯原始碼]

Zsh 不使用 readline,而是使用其自身且更為強大的 Zsh 行編輯器(Zsh Line Editor,ZLE)。它不會讀取 /etc/inputrc~/.inputrc 文件。閱讀 A closer look at the zsh line editor and creating custom widgets 以了解 ZLE 配置。

ZLE 有 Emacs 模式和 vi 模式。如果 VISUALEDITOR 環境變量之一包含字符串 vi,則會使用 vi 模式,否則默認為 Emacs 模式。可以分別使用 bindkey -ebindkey -v 顯式指定 Emacs 模式和 vi 模式。在 vi 模式下按 Esc 鍵的延遲默認是 0.4 秒,你可以通過設置 export KEYTIMEOUT=5 將其縮短至 0.05 秒。

按鍵綁定是通過將與按鍵對應的一個轉義序列映射到一個 ZLE 小部件來分配的。可用的小部件及其作用描述和默認的按鍵綁定可以在 zshzle(1) § STANDARD WIDGETSzshcontrib(1) § ZLE FUNCTIONS 中找到。

在 Zsh 中設置按鍵綁定的推薦方法是使用來自 terminfo(5) 的字符串功能。例如[1][2]

~/.zshrc
# 創建兼容 zkbd 的哈希表;
# 要向此哈希表添加其他鍵,請參閱:man 5 terminfo
typeset -g -A key

key[Home]="${terminfo[khome]}"
key[End]="${terminfo[kend]}"
key[Insert]="${terminfo[kich1]}"
key[Backspace]="${terminfo[kbs]}"
key[Delete]="${terminfo[kdch1]}"
key[Up]="${terminfo[kcuu1]}"
key[Down]="${terminfo[kcud1]}"
key[Left]="${terminfo[kcub1]}"
key[Right]="${terminfo[kcuf1]}"
key[PageUp]="${terminfo[kpp]}"
key[PageDown]="${terminfo[knp]}"
key[Shift-Tab]="${terminfo[kcbt]}"

# 相應地設置鍵
[[ -n "${key[Home]}"      ]] && bindkey -- "${key[Home]}"       beginning-of-line
[[ -n "${key[End]}"       ]] && bindkey -- "${key[End]}"        end-of-line
[[ -n "${key[Insert]}"    ]] && bindkey -- "${key[Insert]}"     overwrite-mode
[[ -n "${key[Backspace]}" ]] && bindkey -- "${key[Backspace]}"  backward-delete-char
[[ -n "${key[Delete]}"    ]] && bindkey -- "${key[Delete]}"     delete-char
[[ -n "${key[Up]}"        ]] && bindkey -- "${key[Up]}"         up-line-or-history
[[ -n "${key[Down]}"      ]] && bindkey -- "${key[Down]}"       down-line-or-history
[[ -n "${key[Left]}"      ]] && bindkey -- "${key[Left]}"       backward-char
[[ -n "${key[Right]}"     ]] && bindkey -- "${key[Right]}"      forward-char
[[ -n "${key[PageUp]}"    ]] && bindkey -- "${key[PageUp]}"     beginning-of-buffer-or-history
[[ -n "${key[PageDown]}"  ]] && bindkey -- "${key[PageDown]}"   end-of-buffer-or-history
[[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}"  reverse-menu-complete

# 最後,確保終端處於應用程序模式,此時 ZLE 處於
# 活動狀態。只有這樣,$terminfo 中的值才有效。
if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
	autoload -Uz add-zle-hook-widget
	function zle_application_mode_start { echoti smkx }
	function zle_application_mode_stop { echoti rmkx }
	add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
	add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
fi

查找歷史記錄[編輯 | 編輯原始碼]

您需要設置 key 數組並確保 ZLE 進入應用程序模式以使用以下說明。請參閱 #快捷鍵綁定

要啟用歷史搜索,請將這些行添加到 .zshrc 文件中:

~/.zshrc
autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search

[[ -n "${key[Up]}"   ]] && bindkey -- "${key[Up]}"   up-line-or-beginning-search
[[ -n "${key[Down]}" ]] && bindkey -- "${key[Down]}" down-line-or-beginning-search

這樣,當按下 UpDown 鍵時,只會顯示與當前光標位置之前匹配的過去命令。

Shift、Alt、Ctrl 和 Meta 修飾鍵[編輯 | 編輯原始碼]

xterm 兼容終端可以使用 user_caps(5) 中的擴展鍵定義,即 ShiftAltCtrlMetaUpDownLeftRightPageUpPageDownHomeEndDel 的組合。請參閱 zkbd 源代碼以獲取修飾鍵和組合鍵的推薦名稱列表。

例如,使用 Ctrl+Left 移動到上一個單詞的開頭,使用 Ctrl+Right 移動到下一個單詞的開頭:

~/.zshrc
key[Control-Left]="${terminfo[kLFT5]}"
key[Control-Right]="${terminfo[kRIT5]}"

[[ -n "${key[Control-Left]}" ]] && bindkey -- "${key[Control-Left]}" behind-word
[[ -n "${key[Control-Right]}" ]] && bindkey -- "${key[Control-Right]}" front-word

另一種方法[編輯 | 編輯原始碼]

該方法會在啟動應用之前,將你的輸入保存在一行當中。

~/.zshrc
ncmpcppShow() { ncmpcpp <$TTY; zle redisplay; }
zle -N ncmpcppShow
bindkey '^[\' ncmpcppShow

命令提示[編輯 | 編輯原始碼]

Zsh 提供了使用提示主題的選項,而對於對主題不滿意(或想要擴展其實用性)的用戶,可以構建自定義提示。

提示主題[編輯 | 編輯原始碼]

提示主題是快速輕鬆地在 Zsh 中設置彩色提示符的方法。有關提示主題以及如何編寫自己的主題,請參閱 zshcontrib(1) § PROMPT THEMES

要使用主題,請確保提示主題系統在 .zshrc 中設置為自動加載。這可以通過添加以下幾行實現:

~/.zshrc
autoload -Uz promptinit
promptinit

然後你可以運行下面的命令查看可用的提示主題:

$ prompt -l

例如,要使用 walters 主題,請輸入:

$ prompt walters

要預覽所有可用的主題,請使用以下命令:

$ prompt -p
手動安裝提示主題[編輯 | 編輯原始碼]

可以手動安裝主題而無需外部配置管理器工具。對於本地安裝,首先創建一個文件夾並將其添加到 fpath 數組,例如:

$ mkdir ~/.zprompts
$ fpath=("$HOME/.zprompts" "$fpath[@]")

現在在此文件夾中創建主題文件的符號鏈接:

$ ln -s mytheme.zsh ~/.zprompts/prompt_mytheme_setup

如果您希望全局安裝主題,請執行以下操作:

# ln -s mytheme.zsh /usr/share/zsh/functions/Prompts/prompt_mytheme_setup

現在您應該能夠使用以下方法激活它:

$ prompt mytheme

如果一切正常,可以相應地編輯 .zshrc

添加提示主題而不為每個主題單獨創建一個文件[編輯 | 編輯原始碼]

除了通過自己的文件添加提示主題外,還可以從另一個文件(如 .zshrc)中添加主題,例如:

~/.zshrc
# 加載 promptinit
autoload -Uz promptinit && promptinit

# 定義主題
prompt_mytheme_setup() {
PS1="%~%# "
}

# 將主題添加到 promptsys
prompt_themes+=( mytheme )

# 加載主題
prompt mytheme

自定義命令提示符[編輯 | 編輯原始碼]

除了所有 shell 都通用的主要左側提示符 PS1PROMPTprompt)之外,Zsh 還支持右側提示符 RPS1RPROMPT),這兩個變量可用於自定義。

其他特殊用途的提示符,例如 PS2PROMPT2)、PS3PROMPT3)、PS4PROMPT4)、RPS1RPROMPT)、RPS2RPROMPT2)和 SPROMPT,在 zshparam(1) § PARAMETERS USED BY THE SHELL 中有說明。

所有提示符都可以使用提示符轉義進行自定義。可用的提示轉義列在 zshmisc(1) § EXPANSION OF PROMPT SEQUENCES 中。

彩色[編輯 | 編輯原始碼]

Zsh 設置顏色的方式與 Bash英語Bash/Prompt customization 不同;您無需使用 terminfo(5) 中的大量 ANSI 轉義序列或終端功能。Zsh 提供了方便的提示轉義來設置前景色、背景色和其他視覺效果;請參閱 zshmisc(1) § Visual effects 以獲取它們的列表及其說明。

顏色可以使用十進制整數、八種最廣泛支持的顏色之一的名稱或十六進制格式的 # 後跟 RGB 三元組來指定。有關更多詳細信息,請參閱 zshzle(1) § CHARACTER HIGHLIGHTING 中 fg=colour 的描述。

命令 描述
%F{color} [...] %f 和前面介紹的 $fg 是一樣的,但是更簡潔。還可以在 F 前面添加數字。
$fg_no_bold[color] 設置文本為非粗體同時設定文本顏色
$fg_bold[color] 設置文本為粗體同時設定文本顏色
$reset_color 重置文本顏色(改為默認顏色)。不會重置粗體設定。使用 %b 來重置粗體設定。可以使用 %f 來簡化配置。
%K{color} [...] %k 設置背景顏色。和非粗體文本顏色一樣。任何單一數字前綴會設置背景為黑色。

大多數終端支持以下英文顏色名稱作為代號:

中文名稱 英文名稱/代號 編號
黑色 black 0
紅色 red 1
綠色 green 2
黃色 yellow 3
藍色 blue 4
洋紅色 magenta 5
青色 cyan 6
白色 white 7
注意: 粗體文本不一定會和普通文本使用同一種顏色。例如, $fg['yellow'] 會使用暗一點的黃色, 而 $fg_bold['yellow'] 可能會使用亮一點的黃色。(譯者註:具體是由你的終端模擬器配置決定的)

與 xterm 256 色兼容的終端模擬器的顏色編號 0–255 可在 xterm-256color 圖表中找到。

正確設置 TERM 環境變量後,可以使用 echoti colorsterminfo(5) 數據庫中找到終端支持的最大顏色數。對於 24 位顏色,還需使用 print $COLORTERM 檢查 COLORTERM 環境變量。如果它返回 24bittruecolor,則即使 terminfo 顯示的數字較小,您的終端也支持 16777216(224)種顏色。

注意:
  • 終端模擬器及其使用的配色方案之間的顏色 0–15 可能有所不同。
  • 許多終端仿真器使用更亮的顏色顯示粗體。
提示:
  • 可以使用命令 print -P "prompt escapes" 測試提示轉義,例如:
    $ print -P '%B%F{red}co%F{green}lo%F{blue}rs%f%b'
  • 如果您使用 24 位顏色,您可能需要在不支持它們的終端中加載 zsh/nearcolor 模塊。例如:
    [[ "$COLORTERM" == (24bit|truecolor) || "${terminfo[colors]}" -eq '16777216' ]] || zmodload zsh/nearcolor
    有關 zsh/nearcolor 模塊的詳細信息,請參閱 zshmodules(1) § THE ZSH/NEARCOLOR MODULE

示例[編輯 | 編輯原始碼]

簡單無色提示的示例:

PROMPT='%n@%m %~ %# '

顯示方式:

用戶名@主機 ~ %

帶顏色的左右雙面提示示例:

PROMPT='%F{green}%n%f@%F{magenta}%m%f %F{blue}%B%~%b%f %# '
RPROMPT='[%F{yellow}%?%f]'

顯示方式如下:

用戶名@主機 ~ % [0]

要使用 16-255 範圍內的顏色和 24 位真彩色,您可以分別使用分配給所需顏色的 0 到 255 之間的數字及其十六進制顏色代碼:

PROMPT='%F{2}%n%f@%F{5}%m%f %F{4}%B%~%b%f %# '
RPROMPT='[%F{3}%?%f]'
PROMPT='%F{#c0c0c0}%n%f@%F{#008000}%m%f %F{#800080}%B%~%b%f %# '
RPROMPT='[%F{#0000ff}%?%f]'

示例 .zshrc 文件[編輯 | 編輯原始碼]

請參閱 dotfiles#用戶倉庫了解更多。

提示與技巧[編輯 | 編輯原始碼]

登錄時自動啟動 X[編輯 | 編輯原始碼]

請參閱 xinit#登錄時自動啟動 X

程序異常退出後恢復終端設置[編輯 | 編輯原始碼]

許多程序會更改終端狀態,並且通常不會在異常退出時恢復終端設置(例如崩潰或遇到 SIGINT 時)。

這通常可以通過執行 reset(1) 來解決:

$ reset

以下部分介紹了避免手動重置終端的方法。

ttyctl 命令[編輯 | 編輯原始碼]

ttyctl 命令可用於「凍結/解凍」終端。要在啟動時凍結交互式 shell,請使用以下命令:

~/.zshrc
ttyctl -f

使用轉義序列重置終端[編輯 | 編輯原始碼]

替代畫線字符集可能會以 ttyctl 無法阻止的方式搞砸終端。

一個簡單的解決方案是從 precmd 鈎子函數輸出重置終端的轉義序列,以便在每次繪製提示之前執行它們。例如,使用轉義序列 \e[0m\e(B\e)0\017\e[?5l\e7\e[0;0r\e8:

~/.zshrc
autoload -Uz add-zsh-hook

function reset_broken_terminal () {
printf '%b' '\e[0m\e(B\e)0\017\e[?5l\e7\e[0;0r\e8'
}

add-zsh-hook -Uz precmd reset_broken_terminal

要測試它是否有效,請運行:

$ print '\e(0\e)B'

記住最近的目錄[編輯 | 編輯原始碼]

目錄棧(dirstack)[編輯 | 編輯原始碼]

Zsh 可以配置 DIRSTACK 相關變量來加速 cd 訪問常用目錄。在你的配置文件中添加下面的配置:

.zshrc
DIRSTACKFILE="$HOME/.cache/zsh/dirs"
if [[ -f $DIRSTACKFILE ]] && [[ $#dirstack -eq 0 ]]; then
  dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
  [[ -d $dirstack[1] ]] && cd $dirstack[1]
fi
chpwd() {
  print -l $PWD ${(u)dirstack} >$DIRSTACKFILE
}

DIRSTACKSIZE=20

setopt autopushd pushdsilent pushdtohome

## Remove duplicate entries
setopt pushdignoredups

## This reverts the +/- operators.
setopt pushdminus

現在你可以使用

dirs -v

來打印目錄棧(dirstack)。使用 cd -<NUM> 來跳轉到以前訪問過的目錄。你還可以在連字符後面使用自動補全,非常方便。

注意:如果您打開了多個 zsh 會話並嘗試 cd,則此操作將不起作用,因為兩個會話在寫入同一個文件時會發生衝突。

cdr[編輯 | 編輯原始碼]

cdr 允許您從自動維護的列表中將工作目錄更改為上一個工作目錄。它將所有條目存儲在跨會話維護的文件中,並且(默認情況下)在當前會話中的終端仿真器之間維護。

有關設置說明,請參閱 zshcontrib(1) § REMEMBERING RECENT DIRECTORIES

zoxide[編輯 | 編輯原始碼]

zoxide 是一個更智能的 cd 命令,只需按幾下鍵,您就可以導航到任何地方。它會記住您經常使用的目錄,並使用評分機制來猜測您想要去的地方。

幫助命令[編輯 | 編輯原始碼]

Bash 不同,Zsh 沒有內置的 help 命令,而是提供 run-help。默認情況下,run-helpman 的別名,可以通過將其添加到命令前面來手動執行,也可以使用鍵盤快捷鍵 Alt+hEsc h 為當前輸入的命令調用它。

由於默認情況下它只是 man 的別名,因此它僅適用於外部命令。為了改進其功能,使其適用於 shell 內置命令和其他 shell 功能,您需要使用 run-help 函數。有關 run-help 及其輔助函數的更多信息,請參閱 zshcontrib(1)

首先加載 run-help 函數,然後刪除現有的 run-help 別名。為了方便起見,可以將 help 別名為 run-help。例如,將以下內容添加到您的 zshrc

autoload -Uz run-help
(( ${+aliases[run-help]} )) && unalias run-help
alias help=run-help

必須單獨啟用助手功能:

autoload -Uz run-help-git run-help-ip run-help-openssl run-help-p4 run-help-sudo run-help-svk run-help-svn

例如,run-help git commit 命令現在將打開 man page git-commit(1),而不是 git(1)

持續 rehash[編輯 | 編輯原始碼]

通常情況下,compinit 不會自動找到 $PATH 中的新可執行文件。例如,在安裝了一個新包之後,/usr/bin/ 目錄下的文件不會立即或自動包含在補全列表中。因此,為了使這些新的可執行文件包含進來,可以運行以下命令:

$ rehash

可以讓這個 rehash 自動發生。[3] 只需在你的 zshrc 文件中包含以下內容:

~/.zshrc
zstyle ':completion:*' rehash true

必要時 rehash[編輯 | 編輯原始碼]

如上所述,但是可以通過配置 pacman 使用鈎子來自動請求 rehash,這不會像上面的持續 rehash 那樣帶來性能損失。要啟用此功能,需要創建 /etc/pacman.d/hooks 目錄和一個 /var/cache/zsh 目錄,然後創建一個鈎子文件:

/etc/pacman.d/hooks/zsh.hook
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/bin/*
[Action]
Depends = zsh
When = PostTransaction
Exec = /usr/bin/install -Dm644 /dev/null /var/cache/zsh/pacman

這樣做的目的是保持文件 /var/cache/zsh/pacman 的修改日期與上次安裝、升級或移除包的時間一致。然後,需要通過在你的 ~/.zshrc 文件中添加以下內容來促使 zsh 在其命令緩存過期時 rehash:

~/.zshrc
zshcache_time="$(date +%s%N)"

autoload -Uz add-zsh-hook

rehash_precmd() {
  if [[ -a /var/cache/zsh/pacman ]]; then
    local paccache_time="$(date -r /var/cache/zsh/pacman +%s%N)"
    if (( zshcache_time < paccache_time )); then
      rehash
      zshcache_time="$paccache_time"
    fi
  fi
}

add-zsh-hook -Uz precmd rehash_precmd

如果在 /var/cache/zsh/pacman 被更新之前觸發了 precmd 鈎子,則補全可能不會生效,直到啟動新的提示符為止。運行一個空命令(例如按 enter)應該是足夠的。

使用 SIGUSR1 的替代必要時 rehash 方法[編輯 | 編輯原始碼]

如上所述,然而鈎子文件看起來是這樣的:

/etc/pacman.d/hooks/zsh-rehash.hook
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/bin/*

[Action]
Depends = zsh
Depends = procps-ng
When = PostTransaction
Exec = /usr/bin/pkill zsh --signal=USR1
警告:這會向所有正在運行的 zsh 實例發送 SIGUSR1。請注意,默認情況下 SIGUSR1 的行為是終止進程,所以當你第一次配置這個設置時,如果沒有加載下面的 trap,所有用戶的(包括登錄 shell)所有正在運行的 zsh 實例將終止。
~/.zshrc
TRAPUSR1() { rehash }

上面的 trap 函數(function trap)可以用 trap 列表(list trap) trap 'rehash' USR1 替換。參見 zshmisc(1) § Trap Functions 了解不同類型的 trap 之間的區別。

這種方法將即時對所有 zsh 實例進行 rehash,無需按下回車鍵來觸發 precmd

ncurses 應用的快捷鍵綁定[編輯 | 編輯原始碼]

將 ncurses 應用程序綁定到按鍵會導致無法交互。使用 BUFFER 變量使其工作。以下示例允許用戶使用 Alt+\ 打開 ncmpcpp英語ncmpcpp:

~/.zshrc
ncmpcppShow() {
BUFFER="ncmpcpp"
zle accept-line
}
zle -N ncmpcppShow
bindkey '^[\' ncmpcppShow

另一種方法,它將保留您在調用應用程序之前在行中輸入的所有內容:

~/.zshrc
ncmpcppShow() {
ncmpcpp <$TTY
zle redisplay
}
zle -N ncmpcppShow
bindkey '^[\' ncmpcppShow

文件管理器的快捷鍵綁定[編輯 | 編輯原始碼]

圖形化文件管理器中使用快捷鍵可能很實用(譯者註:你也可以在 Zsh 中自定義快捷鍵達到這樣的效果)。第一個使用 Alt+Left 讓用戶撤銷最近的 cd 操作,第二個使用 Alt+Up 讓用戶進入上層目錄。這兩個快捷鍵同時也會顯示目錄中的內容。

~/.zshrc
cdUndoKey() {
  popd      > /dev/null
  zle       reset-prompt
  echo
  ls
  echo
}

cdParentKey() {
  pushd .. > /dev/null
  zle      reset-prompt
  echo
  ls
  echo
}

zle -N                 cdParentKey
zle -N                 cdUndoKey
bindkey '^[[1;3A'      cdParentKey
bindkey '^[[1;3D'      cdUndoKey

xterm 標題[編輯 | 編輯原始碼]

如果您的終端仿真器支持,您可以從 Zsh 設置其標題。這允許動態更改標題以顯示有關 shell 狀態的相關信息,例如顯示用戶名和當前目錄或當前正在執行的命令。

xterm 標題使用 xterm 控制序列操作系統命令 \e]2;\a\e]2;\e\\ 設置。例如:

$ print -n '\e]2;My xterm title\a'

將標題設置為

My xterm title

獲得動態標題的一種簡單方法是在 precmdpreexec 鈎子函數中設置標題。有關可用鈎子函數及其說明的列表,請參閱 zshmisc(1) § Hook Functions

通過使用 print -P,您還可以利用 Zsh 的提示轉義。

提示:
  • 標題打印可以拆分為多個命令,只要它們是連續的即可。
  • GNU Screen 將 xterm 標題發送到硬狀態 (%h)。如果您想使用 Screen 的 字符串轉義(例如用於顏色),您應該使用 \e_\e\\ 轉義序列設置硬狀態。否則,如果在 \e]2;\a 中使用字符串轉義,終端仿真器將獲得亂碼標題,因為它無法解釋 Screen 的字符串轉義。
注意:
  • 打印變量時不要使用 print-P 選項,以防止它們被解析為提示轉義符。
  • 打印變量時使用 q 參數擴展標誌,以防止它們被解析為轉義序列。
~/.zshrc
autoload -Uz add-zsh-hook

function xterm_title_precmd () {
	print -Pn -- '\e]2;%n@%m %~\a'
	[[ "$TERM" == 'screen'* ]] && print -Pn -- '\e_\005{2}%n\005{-}@\005{5}%m\005{-} \005{+b 4}%~\005{-}\e\\'
}

function xterm_title_preexec () {
	print -Pn -- '\e]2;%n@%m %~ %# ' && print -n -- "${(q)1}\a"
	[[ "$TERM" == 'screen'* ]] && { print -Pn -- '\e_\005{2}%n\005{-}@\005{5}%m\005{-} \005{+b 4}%~\005{-} %# ' && print -n -- "${(q)1}\e\\"; }
}

if [[ "$TERM" == (Eterm*|alacritty*|aterm*|foot*|gnome*|konsole*|kterm*|putty*|rxvt*|screen*|wezterm*|tmux*|xterm*) ]]; then
	add-zsh-hook -Uz precmd xterm_title_precmd
	add-zsh-hook -Uz preexec xterm_title_preexec
fi

終端仿真器選項卡標題[編輯 | 編輯原始碼]

一些終端仿真器和多路復用器支持設置選項卡的標題。轉義序列取決於終端:

終端 轉義序列 描述
GNU Screen \ek\e\\ Screen 的窗口標題 (%t)。
Konsole \e]30;\a Konsole 的選項卡標題。

Shell 環境檢測[編輯 | 編輯原始碼]

請參閱有關 shell 環境檢測的存儲庫以了解檢測 shell 環境的測試。這包括登錄/交互式 shell、Xorg 會話、TTY 和 SSH 會話。

/dev/tcp 等效項:ztcp[編輯 | 編輯原始碼]

使用 zsh/net/tcp 模塊:

$ zmodload zsh/net/tcp

您現在可以建立 TCP 連接:

$ ztcp example.com 80

更多詳細信息請參閱 zshmodules(1) § THE_ZSH/NET/TCP_MODULEzshtcpsys(1)

在部分命令行上退出 shell 的快捷方式[編輯 | 編輯原始碼]

默認情況下,如果命令行已填滿,Ctrl+d 將不會關閉您的 shell,這可以修復它:

.zshrc
exit_zsh() { exit }
zle -N exit_zsh
bindkey '^D' exit_zsh

pacman -F「未找到命令」處理程序[編輯 | 編輯原始碼]

pacman 包含搜索包含文件的包的功能。以下命令未找到處理程序將在執行未知命令時直接使用 pacman 搜索匹配的包。

~/.zshrc
...
function command_not_found_handler {
    local purple='\e[1;35m' bright='\e[0;1m' green='\e[1;32m' reset='\e[0m'
    printf 'zsh: 未找到命令:%s\n' "$1"
    local entries=(
        ${(f)"$(/usr/bin/pacman -F --machinereadable -- "/usr/bin/$1")"}
    )
    if (( ${#entries[@]} ))
    then
        printf "${bright}$1${reset} 可能位於以下軟件包中:\n"
        local pkg
        for entry in "${entries[@]}"
        do
            # (存儲庫 軟件包 版本 文件)
            local fields=(
                ${(0)entry}
            )
            if [[ "$pkg" != "${fields[2]}" ]]
            then
                printf "${purple}%s/${bright}%s ${green}%s${reset}\n" "${fields[1]}" "${fields[2]}" "${fields[3]}"
            fi
            printf '    /%s\n' "${fields[4]}"
            pkg="${fields[2]}"
        done
    fi
    return 127
}
...
注意:pacman 的文件數據庫與普通同步數據庫是分開的,需要使用 pacman -Fy 來獲取。詳情請參閱 pacman#搜索包含特定文件的包

有關使用 pkgfile 的替代方法,請參閱 #pkgfile「未找到命令」處理程序

使用鍵綁定清除後緩衝區[編輯 | 編輯原始碼]

默認情況下,清除屏幕鍵綁定不會清除大多數終端仿真器上的後緩衝區(您需要向上滾動才能看到的部分)。此問題的一個可能解決方案如下:

~/.zshrc
...
function clear-screen-and-scrollback() {
    printf '\x1Bc'
    zle clear-screen
}

zle -N clear-screen-and-scrollback
bindkey '^L' clear-screen-and-scrollback
...

第三方擴展[編輯 | 編輯原始碼]

配置框架[編輯 | 編輯原始碼]

注意:框架引入了一定程度的抽象和複雜性。它們可以並且經常會引入未定義的行為。如果 shell 出現故障,則「第一個」調試步驟應該是恢復到普通 shell。
  • oh-my-posh — Oh My Posh 是任何 shell 的自定義提示引擎,它能夠使用函數或變量調整提示字符串。
https://github.com/JanDeDobbeleer/oh-my-posh || oh-my-poshAUR
  • oh-my-zsh — 一個流行的、社區驅動的框架,用於管理您的 Zsh 配置。它捆綁了大量有用的函數、幫助程序、插件和主題。
https://github.com/ohmyzsh/ohmyzsh || oh-my-zsh-gitAUR
  • Prezto — Zsh 的配置框架。它帶有模塊,通過合理的默認值、別名、函數、自動完成和提示主題豐富了命令行界面環境。
https://github.com/sorin-ionescu/prezto || prezto-gitAUR
  • ZIM — 具有極快速度和模塊化擴展的配置框架。Zim 非常易於定製,並且帶有一組豐富的模塊和功能,而不會影響速度或功能。
https://github.com/zimfw/zimfw || zsh-zim-gitAUR

插件管理器[編輯 | 編輯原始碼]

  • Antidote — 功能齊全的 Zsh 舊版 Antibody 插件管理器實現。
https://github.com/mattmc3/antidote || zsh-antidoteAUR
  • zinit(原「zplugin」) — 靈活的 Zsh 插件管理器,具有乾淨的 fpath、報告、完成管理、渦輪模式 REVIVED
https://github.com/zdharma-continuum/zinit || zinitAUR
  • zi(原「zplugin」) — zplugin 的替代分支,旨在擴展原始項目,而不是像 zinit 那樣保存和維護原始項目。
https://github.com/z-shell/zi || 未被打包?在 AUR 裡搜索
  • sheldon — 快速、可配置的 shell 插件管理器,用 Rust 編寫 [4]
https://github.com/rossmacarthur/sheldon || sheldon
  • Antigen — Zsh 的插件管理器,靈感來自 oh-my-zsh 和 vundle。 ABANDONED
https://github.com/zsh-users/antigen || antigen-gitAUR
  • zgen — Zsh 的輕量級和簡單插件管理器。 ABANDONED
https://github.com/tarjoilija/zgen || zgen-gitAUR
  • zplug — Zsh 的下一代插件管理器。 ABANDONED
https://github.com/zplug/zplug || zplugAUR

仿 Fish 命令高亮[編輯 | 編輯原始碼]

譯者註:Fish 是一款比較新的終端軟件

Fish 提供了非常強大的命令高亮。如果你希望在 zsh 中使用類似的功能,你可以安裝 zsh-syntax-highlightingzsh-autosuggestions,然後在你的 zshrc 中 source 下面的兩個腳本或其中之一:

source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh

pkgfile「未找到命令」處理程序[編輯 | 編輯原始碼]

pkgfile 包含一個 Zsh 腳本文件,該文件提供了一個 command_not_found_handler 函數,該函數將在輸入無法識別的命令時自動搜索 pkgfile 數據庫。

您需要 source 該腳本才能啟用它。例如:

~/.zshrc
source /usr/share/doc/pkgfile/command-not-found.zsh
注意:可能需要更新 pkgfile 數據庫才能正常工作。有關詳細信息,請參閱 pkgfile#安裝

有關使用 pacman 本機功能的替代方法,請參閱 #pacman -F「未找到命令」處理程序

卸載[編輯 | 編輯原始碼]

在卸載 zsh 之前請先更換默認終端。

警告:如果不遵循下面的步驟可能會導致用戶無法訪問任何終端

運行下面的命令:

$ chsh -s /bin/bash user

每一個使用 zsh 作為默認終端的用戶都需要執行一遍條命令。當完成之後就可以把 zsh 軟件包刪除了。

當然你也也可以以 root 身份修改 /etc/passwd 文件,來批量更改用戶的默認終端。

警告:強烈建議使用 vipw 來修改 /etc/passwd,因為它可以幫助你消滅格式錯誤

例如將下面的配置中的 /bin/zsh

username:x:1000:1000:Full Name,,,:/home/username:/bin/zsh

改成 /bin/bash

username:x:1000:1000:Full Name,,,:/home/username:/bin/bash

另請參見[編輯 | 編輯原始碼]