在这篇 Ask Ubuntu 帖子中,我使用 globstar 来定位PATH
未设置的文件:
$ shopt -s globstar; for v in /**/vim; do [[ -x $v && -f $v ]] && echo "$v"; done
/etc/alternatives/vim
/usr/bin/vim
/usr/bin/X11/vim
现在我想起来,那个输出似乎有点奇怪。/usr/bin/X11
是一个符号链接/usr/bin
:
$ readlink /usr/bin/X11
.
所以,那里有 s 的无限递归X11
,但只有第一个出现在输出中。奇怪的是,只是 a/usr/**
根本没有下降X11
:
$ printf "%s\n" /usr/bin/** | grep X11
/usr/bin/X11
如何协调第一个和最后一个输出?
来自评论:
我在 Ubuntu 16.04 上使用 Bash 版本 4.4.18(1)。
tl;dr - Bash 扩展很复杂,以防止无限的符号链接循环(in
bash >= 4.3
),你和我都误解了它在你发布的命令中所做的事情我假设你有
bash >= 4.3
,因为我无法重现你在 中描述的内容bash 4.2.46
,它会循环直到达到递归限制(如预期的那样)。盯着这个看了一会儿,设置了一个测试目录来模仿你的情况玩。关键是 bash 扩展如何在您的每个示例中发生。扩展的行为不同,取决于它是否跟在 a 之后
/
,而对于我们灵长类动物来说,在看这样的例子时,在这一点上只是存在一些认知失调。从bash shopt 的文档中:
为了说明这是我的测试设置:
导致这个目录结构:
这在我的测试目录中复制了您的发现:
在第一个示例中,glob 扩展为,在没有跟随链接的情况下
(test/nested/looper, test/nested, test)
停止,因为 glob 后面跟着一个looper
/
然后我们附加
/sneaky
到它,得到 set(test/nested/looper/sneaky, test/nested/sneaky, test/sneaky)
。在第二个示例中,glob 扩展为
(test/nested/looper, test/nested/sneaky, test/nested, test/sneaky, test)
(您可以通过删除 来验证| grep sneaky
)同样,这个展开没有跟随
looper
链接,但是在这种情况下我们没有附加到它,因此从我们的结果中/sneaky
删除。../test/nested/looper/sneaky
另一方面,我们继续得到
../test/nested/sneaky
,../test/sneaky
因为当 glob 后面没有跟一个 a 时,它也会抓取文件/