fish
fish是「friendly interactive shell」的縮寫,是一個「交互式的、對用戶友好的 命令行shell」。
fish 被有意設計成不完全與 POSIX 兼容。fish 的作者們認為 POSIX 中存在一些缺陷和矛盾,並通過 fish 簡化的或不同的語法解決這些問題。因此,即使簡單的 POSIX 兼容的腳本也可能需要較多的修改──甚至完全重寫──才能在 fish 中運行。
安裝[編輯 | 編輯原始碼]
安裝 fish包 軟體包。或者安裝開發版的 fish-gitAUR。
安裝完成這後,輸入 fish
即可進入 fish shell。
要查看幫助文檔,在 fish 中輸入 help
,文檔將會在瀏覽器中打開。建議用戶至少讀完文檔中「Syntax overview」這一節內容,因為 fish 的語法和其他 shell 的並不一樣。
在系統中配置 fish[編輯 | 編輯原始碼]
需要考慮的是:是把 fish 設置為默認 shell,也就是用戶登錄時直接進入的 shell,還是通過當前的默認 shell 啟動 fish,並只在交互模式下使用 fish。這裡,我們假設當前的默認 shell 是 Bash。
- 把 fish 設為默認shell:這種方式需要用戶對 fish 的運行機制及其腳本語言有些基本的了解。用戶需要把當前的初始化腳本和環境變量移動到 fish 的環境中。#將 fish 設為默認 shell 中有具體的步驟。
- 只把 fish 用作交互式shell:這種方法「破壞性」較小。Bash 會照常運行所有的初始化腳本,並在此基礎上啟動 fish。#僅將 fish 用作交互式 shell 中有具體的步驟。
將 fish 設為默認 shell[編輯 | 編輯原始碼]
如果你決定把 fish 設為默認的 shell,首先你需要將你的用戶的 shell 改為/usr/bin/fish
。參照 Command-line shell#Changing your default shell 中的步驟。
下一步是把 Bash 的幾個初始化腳本中的操作和配置用 fish 的方法和工具重寫,這些腳本分別有/etc/profile
、~/.bash_profile
、/etc/bash.bashrc
和~/.bashrc
。
需要特別關注的是,在登錄到 fish 中後,你需要儘快檢查、調整環境變量$PATH
的內容。在 fish 中,$PATH
是一個全局環境變量:全局表示作用範圍包含所有函數,並且會在重啟的時候被清除;環境變量則意味著它對 fish 的所有子進程都是可見的。相較於修改直接修改 $fish_user_path
,現在更推薦在配置文件中使用 fish_add_path 來設置路徑,比如
$ fish_add_path -p /路徑_1 /路徑_2 /路徑_3
會將這三個路徑添加到搜索路徑的頭部。
僅將 fish 用作交互式 shell[編輯 | 編輯原始碼]
如果不將 fish 設為默認 shell,就能照常運行 Bash 的初始化腳本。這能夠保證用戶當前的環境變量不受影響並且在 fish 中也能使用,因為 fish 是作為 Bash 的子進程運行的。下面是幾種只把 fish 用作交互式 shell 的方法。
通過 .bashrc 啟動 fish[編輯 | 編輯原始碼]
保持默認 shell 為 Bash 不變,然後添加exec fish
到合適的 Bash 配置文件中,比如.bashrc
。用這種方法,Bash 會正常執行/etc/profile
和/etc/profile.d
中的所有配置文件。相對於後面的幾種方法,這種是最通用的,因為這種方法在本機計算機和 SSH 遠程計算機上都能使用。
- 在這種配置下,如要使用 Bash 而不是接著啟動 fish,需要使用
bash --norc
,以防止Bash加載~/.bashrc
之後執行exec fish
。 - 要讓類似於
bash -c 'echo test'
中的命令在 Bash 中執行而不是啟動 fish,你可以將exec fish
換為if [ -z "$BASH_EXECUTION_STRING" ]; then exec fish; fi
。 - 在父進程不是 fish 的情況下才起動 fish:這種方法可以在更方便地切換到 Bash 的同時繼續使用
~/.bashrc
中的配置。if [[ $(ps --no-header --pid=$PPID --format=cmd) != "fish" ]] then exec fish fi
使用終端模擬器的選項[編輯 | 編輯原始碼]
另一種方法是在啟動終端模擬器時通過添加命令行選項來啟動fish。對於大部分的終端,這個選項是 -e
。比如,要打開 gnome-terminal 並運行fish,可以將 gnome-terminal 的快捷方式改為:
gnome-terminal -e fish
對於不支持設置 shell 的終端模擬器,比如lilyterm-gitAUR,則需要這樣:
SHELL=/usr/bin/fish lilyterm
另外,有些終端可以在設置或配置文件中將 fish 設為默認 shell。
使用終端復用器的選項[編輯 | 編輯原始碼]
要將 fish 設為 tmux 啟動的默認 shell,在~/.tmux.conf
中加入這行:
set-option -g default-shell "/usr/bin/fish"
當 tmux 啟動時,就會自動進入 fish。
配置[編輯 | 編輯原始碼]
fish的配置腳本保存在~/.config/fish/config.fish
。這個文件與 .bashrc
相似,當每次啟動時,fish會執行這個文件中的命令。需要注意的是,如果需要設置長期保留的變量,應該將這個變量設為一個全局變量,而不是將它定義在這些配置腳本中。
用戶定義的函數保存在~/.config/fish/functions
中,文件名為函數名.fish
。
網頁界面[編輯 | 編輯原始碼]
可以在 fish 的交互式網頁配置頁面中修改配色、提示符、函數、變量、歷史記錄和快捷鍵:
$ fish_config
在 IPv6 被完全禁止的環境下,網頁配置界面或許不能起動。參見[1] 和 IPv6#Disable IPv6。
命令補全[編輯 | 編輯原始碼]
fish 可以通過解析 man 的數據生成自動補全規則,這些自動補全規則被保存在~/.config/fish/generated_completions/
。可以運行下面的命令自動更新補齊規則。
$ fish_update_completions
你也可以在 ~/.config/fish/completions/
目錄下放置自己定義的補全規則。/usr/share/fish/completions/
中有更多的例子。
對 Arch Linux 來說, pacman, pacman-key, makepkg, cower, pbget, pacmatic 這些命令的自動補全規則已經在內置在 fish 中了,因為 fish 在開發的時候就包含了很多命令的補全規則。fish 的內存管理足夠智能,不會因為命令補全產生負面影響。
提示與技巧[編輯 | 編輯原始碼]
命令替換[編輯 | 編輯原始碼]
fish 沒有 Bash 式的歷史記錄替換功能(如 sudo !!
)。fish 的開發者在 fish faq 中建議使用交互式的方式調用歷史記錄:上
方向鍵可以按整條命令回顧歷史,而Alt+上
可以回顧命令的單個參數。Alt+S
會在整條命令的最前面加上 sudo
。
不過,fish wiki 中介紹了一些替代方法。雖然這些方法提供的歷史替換功能並不完整,但可用的有 !!
(替換上一條命令)和 !$
(替換上一條命令的最後一個參數)。
串聯命令[編輯 | 編輯原始碼]
在低於 3.0 的版本中,fish 並未實現串聯命令符號 &&
和 ||
,推薦使用 ; and
和 ; or
語法來實現相似的效果。也可以參照 fish wiki,設置按鍵綁定來自動替換符號。
取消問候語[編輯 | 編輯原始碼]
默認情況下,每次啟動時 fish 都會列印問候語。如要不顯示問候語,可以在 fish 中運行:
set -U fish_greeting
讓 su 默認啟動 fish[編輯 | 編輯原始碼]
如果 su 目標用戶的默認 shell 是 Bash,但是你想使用 fish 作為 shell 的話,可以添加一個 su
函數覆蓋默認的 su 命令,在切換用戶的時候自動使用 fish:
function su /bin/su --shell=/usr/bin/fish $argv end
登錄 fish 時自動啟動 X[編輯 | 編輯原始碼]
把下面配置添加到 ~/.config/fish/config.fish
,即可在登錄 tty1 的時候自動啟動 X。
# Start X at login if status --is-login if test -z "$DISPLAY" -a $XDG_VTNR = 1 exec startx -- -keeptty end end
如果在使用 fish 作為交互 shell,需要把例子中的 is-login
換為 is-interactive
。
在提示符中增加 git 狀態[編輯 | 編輯原始碼]
當你處在一個 git 目錄中時,如果你想在 fish 的提示符中顯示分支和修改的相關信息,可以仿照以下的例子編寫 fish_prompt
函數:
~/.config/fish/functions/fish_prompt.fish
function fish_prompt set -l last_status $status if not set -q __fish_git_prompt_show_informative_status set -g __fish_git_prompt_show_informative_status 1 end if not set -q __fish_git_prompt_color_branch set -g __fish_git_prompt_color_branch brmagenta end if not set -q __fish_git_prompt_showupstream set -g __fish_git_prompt_showupstream "informative" end if not set -q __fish_git_prompt_showdirtystate set -g __fish_git_prompt_showdirtystate "yes" end if not set -q __fish_git_prompt_color_stagedstate set -g __fish_git_prompt_color_stagedstate yellow end if not set -q __fish_git_prompt_color_invalidstate set -g __fish_git_prompt_color_invalidstate red end if not set -q __fish_git_prompt_color_cleanstate set -g __fish_git_prompt_color_cleanstate brgreen end printf '%s%s %s%s%s%s ' (set_color $fish_color_host) (prompt_hostname) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal) (__fish_git_prompt) if not test $last_status -eq 0 set_color $fish_color_error end echo -n '$ ' set_color normal end
然而,fish 已經拋棄了這種方式,參見 fish-shell git。作為替代,fish 現在內置了Informative Git Prompt,該功能可以通過 fish_config
啟用。
在 SSH 中用彩色顯示主機名[編輯 | 編輯原始碼]
如果需要在通過 SSH 登錄到 fish 時用不同的顏色標記提示符中的主機名,可以將以下內容添加到函數 fish_prompt
中,或者添加到 fish 的配置文件中。這裡以紅色為例:
~/.config/fish/functions/fish_prompt.fish
... if set -q SSH_TTY set -g fish_color_host brred end ...
ssh-agent 問題[編輯 | 編輯原始碼]
在fish中,eval (ssh-agent)
會因為變量的設置方式而報錯。一個變通的方案是使用 csh 風格的選項-c
:
$ eval (ssh-agent -c)
"command not found" 事件函數[編輯 | 編輯原始碼]
fish 包含了一個響應「命令未找到」("command not found")事件的函數 fish_command_not_found
。當遇到一個當前系統不存在的命令時,這個函數會使用 pkgfile包 在官方倉庫中查找哪個軟體包擁有這條命令,而如果 pkgfile 不存在則回落使用 pacman -F
作為替代。
從 fish 3.2.2 開始,因為 pacman -F
嚴重的卡頓問題,所以 fish_command_not_found
不會再使用它作為回落。
可以寫一個 fish_command_not_found
函數來替換掉 fish 自帶的。比如在「命令未找到」時只列印錯誤消息,這樣就不會有卡頓現象:
$ function fish_command_not_found __fish_default_command_not_found_handler $argv[1] end
然後保存這個函數:
$ funcsave fish_command_not_found
從 jobs 中刪除進程[編輯 | 編輯原始碼]
當退出 fish 的時候,所有後台進程也會終止。為了讓一個任務即使在 fish 退出了之後也繼續運行,需要先輸入 disown
命令再退出。比如說,這個例子在後台起動 Firefox 然後 disown
它:
$ firefox & $ disown $ exit
這樣即使退出了 fish,Firefox 也會繼續運行。請查閱 fish 的 disown(1) 了解更多細節。
快速設置別名[編輯 | 編輯原始碼]
如果想要快速設置一個持久化的別名(即使 fish 退出也不會失效),可以使用這種方法:
$ alias FooAliasName "foo --option" $ funcsave FooAliasName
而在 fish 3.0 之後的版本中,alias
增加了 --save(-s)
選項。
$ alias -s FooAliasName "foo --option"
別名會自動保存,這樣就不需要再執行 funcsave
。如果想查看或者編輯所有的函數,可以運行 fish_config
,然後在網頁界面的 Function 標籤下進行配置。
如要獲取更多文檔,查閱 alias - create a function — fish-shell。
另請參閱[編輯 | 編輯原始碼]
- https://fishshell.com/ - 主頁
- https://fishshell.com/docs/current/ - 文檔
- https://hyperpolyglot.org/unix-shells - Shell 語法對照表(Shell 的「羅塞塔石碑「)
- https://github.com/fish-shell/fish-shell - fish 的 GitHub 倉庫