是否有解决 Debian 文件完成垃圾 $_ 的方法?

是否有解决 Debian 文件完成垃圾 $_ 的方法?

我在 Slackware linux 上有多年的经验,从来没有见过这个问题。最近我一直在管理 Debian 服务器,这已经成为一种烦恼。

我经常在 bash 命令中使用“$_”来重复先前输入的命令的最后一个参数。有时,我会出现以下行为:

dschrag@mo:~/dev/dancer$ ls -l app/db/schema/
总计 12
-rw-r--r-- 1 dschrag dschrag 268 5 月 19 日 10:51 gau_account.sql
-rw-r--r-- 1 dschrag dschrag 558 5 月 19 日 13:02 gau_import.sql
-rw-r--r-- 1 dschrag dschrag 270 五月 19 13:09 gau_source.sql
dschrag@mo:~/dev/dancer$ cd $_
-bash: cd: _filedir: 没有这样的文件或目录
dschrag@mo:~/dev/dancer$

我环顾四周,发现它_filedir被用在/usr/share/bash-completion/bash_completion.

我不假思索地使用文件完成功能,以至于我很难弄清楚发生此故障时我正在做什么。有没有人不厌其烦地深入研究这个问题?

答案1

您已启用可编程完成(“bash 完成”)。这是通过 source/etc/bash_completion/usr/share/bash-completion/bash_completionbashrc 中的某个位置来完成的。例如,在 jessie 的 bashrc 骨架中:

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
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

其中一项完成工作是覆盖$_。快速解决方法是不加载 bash-completion。

complete-filename另一种解决方法是使用该函数而不是该函数来完成文件名补全complete。这意味着按ESC,/Alt+ /(取决于您的终端设置)而不是Tab。您可以使用bind或 通过编辑来更改这些键所绑定的键~/.inputrc

而且,我想,针对 bash-completion 提交一份错误报告。

答案2

简单的追踪

首先,您可以弄清楚当您使用 bashcd命令补全时实际发生了什么:

$ complete -p | grep cd
complete -F _filedir_xspec cdiff
complete -o nospace -F _cdrecord wodim
complete -o nospace -F _cdrecord cdrecord
complete -o nospace -F _cd cd

您可以看到_cd当您使用完成时将调用一个函数cd。所以你知道_cd函数内部发生了一些事情导致你的$_变量值被改变。

查看_cd功能:(在我的 Ubuntu 12.04.4 中,它位于/etc/bash_completion

# This meta-cd function observes the CDPATH variable, so that cd additionally
# completes on directories under those specified in CDPATH.
#
_cd()
{
    local cur IFS=$'\n' i j k
    _get_comp_words_by_ref cur

    # try to allow variable completion
    if [[ "$cur" == ?(\\)\$* ]]; then
        COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
        return 0
    fi
    ....
        _filedir -d

    if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
        i=${COMPREPLY[0]}
        if [[ "$i" == "$cur" && $i != "*/" ]]; then
            COMPREPLY[0]="${i}/"
        fi
    fi

    return 0
}

它会做很多事情,导致你的旧$_迷失。也许你的线路有问题_filedir -d。 (在我的测试中,我被$_更改为-d

为了防止你想要的东西$_丢失,你可以在进入函数时立即保存它的值,然后在离开之前_cd恢复该值:$__cd

_cd()
{
    local __=$_

    ....

    : $__
    return 0
}

这里的技巧是:,它意味着在 中不执行任何操作bash,并且它有一个参数$__(这是您想要的$_值),导致在您进入函数$_之前设置为旧值。_cd

结论

bash completion做到不浪费变量是非常困难的$_。在上面的示例中,您仅使用cd.对于 中的其他函数bash_completion以及 下的所有文件/etc/bash_completion.d/,您必须执行相同的操作。这不是一个可靠的解决方案。

如果您想获取最后一个命令行的最后一个参数,请尝试使用bash history expansion

$ echo 1 2 3
1 2 3
$ echo !$
echo 3
3

相关内容