Fish Shell 命令速查表 - Fish Shell 常用命令与配置大全

Fish 把语法高亮、自动补全、历史模糊搜索做成了默认行为,装完就能用,这是它和 Bash 最大的区别——不是功能更多,而是省掉了配 oh-my-zsh 那几步。真正需要下功夫的是语法差异:Fish 的 if/for/while/switch/function 都用 end 收尾,变量用 set 而非 export,列表与索引的写法也和 Bash 不同,数组下标从 1 开始。迁移时最容易出错的往往不是交互命令,而是把 .bashrc 里的片段直接搬过来。表里按变量作用域、流程控制、函数别名、字符串管道、配置主题、历史快捷键分组列出对应写法,遇到 Bash 习惯时先翻这张对照表,再决定是改脚本还是加一层 sh -c 兜底。

系统与运维·共 36 条命令·最后更新 2026-07-21

典型使用场景

面向从 bash/zsh 切到 fish 之后被语法绊住的人。fish 不是「换个提示符的 bash」:变量必须用 set 命令赋值而不是 VAR=value 写法,没有 $(...) 之外的 process substitution,列表默认按整体拼接而不做单词切分,.bashrc 直接 source 过来几乎必报错。本表把这几处真正会卡人的差异和三档变量作用域(local/global/universal)讲清楚,再补上历史搜索、字符串处理与 fisher 插件安装,够你在一周内完成迁移。

变量与作用域 7

set name "John"
设置变量
echo $name
使用变量
set -x PATH /usr/local/bin $PATH
设置环境变量(导出)
set -U fish_user_paths /usr/local/bin $fish_user_paths
设置通用变量(持久化)
set -l local_var "value"
局部变量(仅当前函数)
set -g global_var "value"
全局变量
set -e name
删除变量

流程控制 5

if test -f file.txt echo "exists" end
条件判断(文件存在)
if test $count -gt 5 echo "many" else echo "few" end
if-else 分支
for file in *.txt echo $file end
遍历文件
while read -l line echo $line end < file.txt
逐行读取文件
switch $status case 0 echo "success" case "*" echo "failed" end
多分支判断

函数与别名 7

function greet echo "Hello $argv" end
定义函数,$argv 接收参数
funcsave greet
保存函数到配置文件
functions
列出所有函数
functions greet
查看指定函数定义
alias cls="clear"
创建别名
abbr -a gco "git checkout"
创建命令缩写(输入后自动展开)
funced greet
交互式编辑函数

字符串与管道 6

string length "hello"
获取字符串长度
string split "," "a,b,c"
按分隔符分割字符串
string join ";" "a" "b" "c"
用分隔符连接字符串
string replace "old" "new" "hello old"
替换字符串
string match -r "^\d+" "123abc"
正则匹配
echo "data" | string upper
管道转大写

配置与主题 6

fish_config
Web 界面配置主题和提示符
fish_config theme choose Nord
命令行切换主题
set -U fish_greeting ""
取消欢迎语
fish_update_completions
更新补全脚本
cat ~/.config/fish/config.fish
查看配置文件
fisher install jorgebucaran/autopair.fish
用 fisher 安装插件

命令历史与快捷键 5

history
查看命令历史
history search "git"
搜索历史命令
history delete "rm -rf"
删除指定历史记录
Ctrl+R
增量搜索历史命令
Alt+← / Alt+→
按单词移动光标

参数矩阵

参数作用示例
set -x / -g / -U / -l / -e依次为导出(环境)变量、全局变量、通用(跨会话持久)变量、局部变量与删除set -U fish_user_paths /usr/local/bin $fish_user_paths
fish_greeting登录时的欢迎语,设为空字符串即可去掉启动横幅set -U fish_greeting ""
abbr -a命令缩写,输入前缀后自动展开且不进入历史,比 alias 更适合替代命令abbr -a gco "git checkout"
string内置字符串工具子命令,替代 bash 里的 cut/sed/tr/grep 组合string split "," "a,b,c"
funcsave把当前交互式定义的函数持久化进配置文件,重开终端仍在funcsave greet

易错点与避坑指南

现象把 .bashrc 里 export PATH=... 直接搬到 fish,执行后 PATH 没变,PATH 里出现一个字面量。

原因fish 里 export VAR=value 不是合法语法,变量必须用 set 命令赋值并带 -x。

处置改成 set -x PATH /usr/local/bin $PATH;要永久生效用 set -U fish_user_paths /usr/local/bin $fish_user_paths。

现象交互式定义的函数关掉终端就没了,下次又要重打一遍。

原因fish 不会自动把交互式函数写回配置文件。

处置定义后执行 funcsave greet 持久化;改动已保存的函数时用 funced greet 编辑。

现象启动时报 fish: Unknown command: [... 一堆语法错误。

原因把 bash 的 [ ] 条件语法直接搬过来,fish 用 test 而不是方括号,且 end 收尾结构不同。

处置改写成 if test $count -gt 5 / else / end 这类 fish 原生结构,逐块替换。

现象alias 定义后想禁用它时 alias name 报错说不存在。

原因fish 里 alias 是函数,删除要用 functions -e name,而不是 bash 的 unalias。

处置用 functions -e name 删除;对命令类替换优先改用 abbr -a,展开更干净。

现象PATH 里手动加的目录重启终端后又没了。

原因用 set -x 写入的只是本次会话的导出变量,没有落到持久化的 universal 变量。

处置用 set -U fish_user_paths /usr/local/bin $fish_user_paths 让它跨会话保留。

排障路径

  1. 1确认配置到底生效了没有

    cat ~/.config/fish/config.fish

    fish 配置只读这一个文件(不含 .bashrc);改完执行 source ~/.config/fish/config.fish 立即重载。

  2. 2找一条以前打过的长命令

    history search "git"

    等价于 Ctrl+R 的交互式增量搜索;history delete "rm -rf" 可清掉危险记录。

  3. 3查某个函数/别名的定义

    functions && functions greet

    functions 列出全部,functions greet 打印单条定义,据此判断它是否被覆盖。

  4. 4装插件

    fisher install jorgebucaran/autopair.fish

    fisher 是 fish 的插件管理器;装完检查 functions 确认插件函数已被加载。

命令示例

导出一个环境变量并查看它

set -x PATH /usr/local/bin $PATH

-x 等价于导出,子进程能继承;这是替换掉 bash 里 export PATH=... 的正确 fish 写法。

把一个目录永久加入 PATH

set -U fish_user_paths /usr/local/bin $fish_user_paths

通用变量会落盘并跨会话生效,反复执行不会重复累积同一目录。

按逗号切分字符串

string split "," "a,b,c"

string 是 fish 内置的字符串工具,能替代 bash 里 cut、sed、tr、grep 的组合。

用命令缩写替代别名

abbr -a gco "git checkout"

输入前缀后按空格即展开,且不像 alias 那样进入历史记录,适合替代命令。

常见坑与注意事项

  • 不要把 bash 的 export PATH=... 直接粘进 fish,fish 没有这条语法,PATH 里会出现字面量而目录没加上。
  • fish 里所有赋值都要走 set 命令,VAR=value 形式不会创建变量。
  • if / for / while / function / switch 都必须用 end 收尾,照搬 bash 的 fi、done、esac 会直接报语法错。
  • 交互式定义的函数不会自动持久化,务必 funcsave 一次,否则重开终端全部白写。
  • 想让 PATH 改动长期有效就用 set -U fish_user_paths,只在当前会话 set -x 的效果关掉终端即消失。

提示

  • Fish 的 if/for/function/switch 用 end 结尾,不需要 fi/done/esac。
  • set -U 设置通用变量,持久化到配置文件,所有 Fish 会话共享。
  • Fish 开箱即用自动补全,按 Tab 即可,按 Alt+→ 接受建议。
  • fisher 是 Fish 的插件管理器:curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher。
  • abbr 比 alias 更轻量,输入缩写后按空格会自动展开为完整命令。
  • Fish 不兼容 POSIX Shell 语法,不能直接用 bash 脚本,但语法更直观。
  • fish_config 用 fzf 交互改 PATH:set -U fish_user_paths $fish_user_paths ~/go/bin,永久生效且不重复写入。
  • fish -c "命令" 可在脚本或测试里跑单条 Fish 命令,比开交互 shell 更快验证语法。
  • 用 set -q 判断变量是否存在:set -q VAR; and echo yes,避免 $VAR 未定义时展开报错。

常见问题

为什么我把 .bashrc 里的 export PATH=... 搬到 fish 里就没效果?

fish 不认 VAR=value 这种写法,也不会解析 export 这条命令,fish 会把整行当成一个普通命令名去找,然后报未知命令,于是 PATH 里可能出现一个字面量。fish 里的正确写法是 set -x PATH /usr/local/bin $PATH,-x 表示导出为环境变量,变量以美元符号加名字引用。

fish 里的条件判断和循环为什么不用 fi、done?

因为 fish 用统一的块结束关键字 end,if、for、while、function、switch 全都用 end 收尾,不需要成对的 fi/done/esac。迁移时看到 if 后面没有 end 之外的 fi、for 后面也没有 done,就是这个原因。

我手动往 PATH 里加的目录,重开终端后就没了?

因为那只是当前会话的变量,没有持久化。用 set -U fish_user_paths /usr/local/bin $fish_user_paths 把目录写进通用变量,它会存到配置里、跨会话保留,而且重复设置不会造成 PATH 里出现多份同样的条目。想在图形界面里改,fish_config 提供的 PATH 页签做的也是同一件事。

在交互式终端里定义好的函数,关掉终端就消失了?

交互式定义的函数只存在于当前会话,除非你显式保存。定义完执行 funcsave greet,函数体就会被写进配置文件,下次开终端还在。写错了用 funced greet 交互式重新编辑,改完同样要 funcsave 才会落盘。

fish 的 -l、-g、-U、-x 四个标记分别管什么?

都是 set 的作用域开关:-l 局部变量,只在当前函数或块内可见;-g 全局变量,当前会话共享;-U 通用变量,写入配置文件并跨会话持久;-x 导出为环境变量,子进程能读到。函数内部用 -l 避免污染全局,PATH 这类要传给外部命令的才用 -x,要跨终端保留的用 -U。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们