我在 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_completion
bashrc 中的某个位置来完成的。例如,在 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