Bash 补全在子 shell 中不起作用

Bash 补全在子 shell 中不起作用

当我启动 bash 子 shell(通过bash从命令提示符调用)时,所有 tab 补全都停止工作。complete新 shell 中的命令变为空:

$ complete
[...]
complete -F _apport-collect apport-collect
complete -F _filedir_xspec vim
complete -o dirnames -o filenames -F _apport-bug ubuntu-bug
complete -F _known_hosts ftp
complete -F _longopt units
complete -F _longopt uname
complete -F _service /etc/init.d/network-manager
complete -F _longopt touch
complete -F _longopt ldd
complete -F _command then
complete -F _known_hosts rlogin
complete -F _service /etc/init.d/sddm
complete -F _service /etc/init.d/lvm2-lvmpolld
complete -F _command command
complete -F _longopt sha384sum
complete -F _known_hosts fping6
complete -F _longopt rm
complete -F _service /etc/init.d/cryptdisks
complete -F _service /etc/init.d/binfmt-support
$ bash
$ complete
$

我如何才能让 tab 自动补全功能在子 shell 中也能正常工作?我的配置文件或 bashrc 中是否缺少某些内容?

编辑:在 ubuntu 中,补全是默认存在的(不是我添加的)。/etc/bash.bashrc提到了补全,但是该部分默认被注释掉了(不是我做的):

# enable bash completion in interactive shells
#if ! shopt -oq posix; then
#  if [ -f /usr/share/bash-completion/bash_completion ]; then
#    . /usr/share/bash-completion/bash_completion
#  elif [ -f /etc/bash_completion ]; then
#    . /etc/bash_completion
#  fi
#fi

/etc/profile执行中的所有脚本/etc/profile.d,其中包含加载完成的脚本:

# shellcheck shell=sh disable=SC1091,SC2039,SC2166
# Check for interactive bash and that we haven't already been sourced.
if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then

    # Check for recent enough version of bash.
    if [ "${BASH_VERSINFO[0]}" -gt 4 ] || \
       [ "${BASH_VERSINFO[0]}" -eq 4 -a "${BASH_VERSINFO[1]}" -ge 1 ]; then
        [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" ] && \
            . "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion"
        if shopt -q progcomp && [ -r /usr/share/bash-completion/bash_completion ]; then
            # Source completion code.
            . /usr/share/bash-completion/bash_completion
        fi
    fi

fi

两个 bash 会话似乎都是用相同的参数开始的:

$ complete
...
complete -F _service /etc/init.d/cryptdisks
complete -F _service /etc/init.d/binfmt-support
$ echo $-
himBHs
$ bash
$ complete
$ echo $-
himBHs

我的bash命令没有任何别名:

$ type bash
bash is /usr/bin/bash

答案1

看起来默认补全是由/etc/profile(进而执行/etc/profile.d/bash_completion.sh)加载的。然而,在非登录 shell 中,/etc/profile不会执行,因此不会加载补全。

如果我启动登录 bash 子shell,则会加载补全内容:

$ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Login shell
$ complete | wc -l
214
$ bash
$ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Not login shell
$ complete | wc -l
0
$ exit
exit
$ bash --login
$ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Login shell
$ complete | wc -l
214

所以基本上,我必须明确地在非登录 shell 中加载补全,因为它们默认不会加载(至少在我的设置上不会)。

相关内容