防止 bash 完成更改下划线变量 $_

防止 bash 完成更改下划线变量 $_

在 bash 中使用制表符补全时,$_变量会被更改:

$ mkdir test
$ cd <TAB><TAB> $_
bash: cd: -d: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]

<TAB><TAB>将列出当前目录中的所有文件,但我最终不会使用输出并写入$_。在这一行中执行的命令将只是cd $_。)

预期的行为将变为./test

如何防止 bash 完成更改$_

答案1

您正在使用bash-completion包(或衍生品)。对于命令的每个参数完成cd(如输出所示complete -p):

complete -o nospace -F _cd cd

调用该_cd函数来确定完成情况(为简洁起见,稍作编辑):

_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d
        return 0
    fi
    ....

例如,当您完成未CDPATH设置的目录时,所见命令的最后一次看到的参数是-d,并且它会自动放置在 中_。该函数中还有其他几个具有类似副作用的代码路径。

由于_是 bash 内部,因此传统的保存/恢复(至于IFS)不会像希望的那样工作。你可以用一点技巧来做到这一点:

_cd()
{
    local save_="$_"
    ...
    : $save_
    return 0

您必须_在进入函数时立即保存,:这是空命令,它本身不执行任何操作,但具有命令的常见副作用,例如设置_。每个潜在破坏性功能的每个返回点都需要此恢复操作。这里也有一个微妙之处:通常_在函数返回后立即设置(如预期的那样,到函数调用的最后一个参数),这将使该方法无效。但是,当调用完成函数时不会发生这种情况,因为它不是显式调用的。我不认为这非常强大......

(我更喜欢历史扩展,并坚持!$哪个不会遇到这个问题。)

相关内容