Bash 补全在子 shell 中不起作用

Pie*_*erV 4 command-line bash auto-completion

当我启动 bash 子 shell(通过bash从命令提示符调用)时,所有选项卡补全都会停止工作。该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
$
Run Code Online (Sandbox Code Playgroud)

如何让制表符补全也能在子 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
Run Code Online (Sandbox Code Playgroud)

/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
Run Code Online (Sandbox Code Playgroud)

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

$ complete
...
complete -F _service /etc/init.d/cryptdisks
complete -F _service /etc/init.d/binfmt-support
$ echo $-
himBHs
$ bash
$ complete
$ echo $-
himBHs
Run Code Online (Sandbox Code Playgroud)

我的bash命令没有别名:

$ type bash
bash is /usr/bin/bash
Run Code Online (Sandbox Code Playgroud)

Pie*_*erV 5

看起来默认的补全是由/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
Run Code Online (Sandbox Code Playgroud)

所以基本上,我必须在非登录 shell 中显式加载完成,因为默认情况下它们不会加载(至少在我的设置中不会加载)。