补全功能默认未启用,需确认bash-completion是否加载:检查shell是否为bash、包是否安装、/etc/profile.d/bash_completion.sh或~/.bashrc中是否有source语句并重载,新命令需手动添加补全脚本,alias不支持补全。

补全功能默认没开?先确认 bash-completion 是否已加载
很多 Linux 发行版(如 Ubuntu、Debian)默认不启用 bash-completion 的完整补全规则,只保留基础的文件名/命令名补全。你输入 git checkout <tab><tab></tab></tab> 却只看到文件列表,不是分支名——说明补全脚本没生效。
检查是否已加载:complete -p | grep git —— 如果无输出,或只显示类似 complete -o bashdefault -o default git,说明没走高级补全逻辑。
- 运行
ls /usr/share/bash-completion/completions/git,存在即表示包已安装 - 确认
/etc/profile.d/bash_completion.sh或/etc/bash.bashrc中有类似[ -f /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion的加载语句 - 若用的是较新系统(如 Ubuntu 22.04+),补全脚本路径可能是
/usr/share/bash-completion/completions/,而非旧版的/etc/bash_completion.d/
补全脚本放哪才真正生效?路径和权限要对
补全脚本不会自动被发现,必须放在 Bash 启动时明确 source 的位置,且不能有执行权限(.bash_completion 是 source 文件,不是可执行脚本)。
- 推荐位置:
/usr/share/bash-completion/completions/(系统级,需 root)或~/.local/share/bash-completion/completions/(用户级,无需 sudo) - 文件名必须与命令名一致:
mytool的补全脚本必须叫mytool(无扩展名),不能叫mytool.bash - 不要
chmod +x补全脚本——Bash 加载它时是source执行,不是./运行;加执行权限反而可能触发 shell 解析错误 - 如果放在
/etc/bash_completion.d/,需确保该目录已被主bash_completion脚本遍历加载(检查其末尾是否有for f in /etc/bash_completion.d/*; do [ -f "$f" ] && . "$f"; done)
自定义补全函数里最容易写错的三件事
自己写 _mycmd() 函数时,90% 的失败源于这三个细节:
-
COMP_WORDS和COMP_CWORD必须在函数开头就用_init_completion初始化(或手动赋值),否则COMP_CWORD可能为 0 导致所有逻辑错位 -
COMPREPLY必须是数组:写成COMPREPLY=("a" "b"),而不是COMPREPLY="a b"(后者会被当做一个字符串,补全只出一个选项) - 子命令判断要用
case "${COMP_WORDS[1]}" in,别漏掉引号——如果用户输mycmd "prod env",没引号会把空格拆成两个单词,COMP_WORDS[1]就不是预期值
示例片段(正确):_mycmd() { _init_completion || return; local cur="${COMP_WORDS[COMP_CWORD]}"; case "${COMP_WORDS[1]}" in deploy) COMPREPLY=($(compgen -W"dev test prod" -- "$cur")); esac; }
补全失效时怎么快速定位?别 reload 整个 shell
改完补全脚本后,不用 source ~/.bashrc 重载全部配置——太慢,还可能覆盖临时变量。直接调试更高效:
- 临时激活:
source /usr/share/bash-completion/completions/git(或你的脚本路径),再试git checkout <tab></tab> - 查看当前补全注册:
complete -p mycmd,输出应含-F _mycmd;若显示-o filenames为主,说明函数没注册成功 - 手动触发补全函数调试:
_mycmd; echo "${COMPREPLY[@]}",能立刻看到生成的候选列表,比反复 Tab 更快 - 注意:补全函数中不能有
set -e或未捕获的exit,否则整个补全流程会静默中断,连报错都不显示
真正麻烦的从来不是写函数,而是补全脚本被加载的时机和上下文——它依赖于 Bash 初始化阶段的一连串 source 顺序,差一行路径或少一个引号,就彻底静默失效。











