意外的 Bash glob 完成使用第一个匹配,即使不明确

G-W*_*Wiz 5 linux bash shell

如果我在目录中有以下文件:

$ ls
a-file-1
b-file-2
something-else
Run Code Online (Sandbox Code Playgroud)

我输入

$ cat *file*<TAB>
Run Code Online (Sandbox Code Playgroud)

该行意外更新为

$ cat a-file-1 |
Run Code Online (Sandbox Code Playgroud)

(管道表示光标)即使 glob 也匹配b-file-2. 有点奇怪的是,如果我启动另一个 shell,我会在 double- 上得到一个匹配列表TAB(我更喜欢):

$ cat *file*<TAB><TAB>
a-file-1  b-file-2
$ cat *file*|
Run Code Online (Sandbox Code Playgroud)

问:这种行为是如何配置的?我想在登录外壳中有第二个行为。

似乎登录 shell 获得了第一个行为,非登录 shell 获得了第二个行为。但是, my~/.bash_profile所做的只是 kick off ~/.bashrc。(我没有.profile。)似乎我必须在某处更改配置。

shopt区别是,只有登录shell都有extglob onhostcomplete offlogin_shell on而改变这些不改变上述行为。set -o输出是一样的。试过了,set show-all-if-ambiguous on但没有效果。我正在使用 Ubuntu 14.04.1。

更新关于通过@mpy评论

在非登录 shell 中,当我在 glob 中包含一个基本目录并按 Alt-G 时,行为与我使用TABTAB. 这是我想在登录 shell 中配置的后一种特定行为。

Alt- G

$ ls dir/*file*<Alt-G>
Run Code Online (Sandbox Code Playgroud)

更新到

$ ls dir/|
Run Code Online (Sandbox Code Playgroud)

删除 glob 并且不打印任何匹配项。而TABTAB输出匹配

$ ls dir/*file*<TAB><TAB>
a-file-1  b-file-2
$ ls dir/*file*|
Run Code Online (Sandbox Code Playgroud)

Pet*_*des 3

在 Ubuntu 14.04 中,默认情况下我会遇到可怕的首匹配扩展行为,但我认为这是可编程完成中的某些错误。

之后shopt -u progcomp,我得到了很好的列表扩展行为。

您的登录与非登录 shell 行为可能是由于获取.bash_profile/etc/profile,或不获取。(或者你的登录 shell 没有获取/etc/bash.bashrc.bashrc,如果你的个人资料没有来源它/它们。)

更新:追踪了可编程完成中的错误:打开set -x,并查看了点击后运行的所有命令的输出TAB。找到glob表达式变成列表的地方,发现在/usr/share/bash-completion/bash_completion

问题出在这里:(搜索 xspec 以找到这些行)

xspec=${1:+"!*.@($1|${1^^})"}
x=$( compgen -f -X "$xspec" -- "$quoted" ) &&
Run Code Online (Sandbox Code Playgroud)

"$quoted"缺少引号,因此它在完成处理 shell 函数中得到扩展。 $quoted在脚本中其他地方的双引号内使用,所以我非常有信心它应该被引用,这是解决这个问题的正确方法。

报告为https://bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1387057,有望在上游得到修复并很快进入所有发行版。