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