globstar 何时下降到符号链接目录?

globstar 何时下降到符号链接目录?

这个询问 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)。

答案1

tl;dr - Bash 扩展很复杂,可以防止无限符号链接循环(在bash >= 4.3),并且你和我都误解了它在你发布的命令中所做的事情

我假设你有,bash >= 4.3因为我无法重现你在 中描述的内容bash 4.2.46,它会循环直到达到递归限制(如预期)。

盯着这个看了一会儿,并设置了一个测试目录来模拟您的情况。关键在于 bash 扩展如何在每个示例中发生。根据扩展是否后跟 ,它的行为会有所不同/,并且对于我们灵长类动物来说,在查看这样的示例时,在这一点上存在一些认知失调。
来自bash shopt 的文档:

globstar
如果设置,文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。如果模式后跟“/”,则仅目录和子目录匹配。

为了说明这里是我的测试设置:

$ mkdir -p test/nested
$ cd test
$ touch sneaky
$ touch nested/sneaky
$ cd nested
$ ln -s . looper
$ cd ..

产生这样的目录结构:

test/
  - sneaky
  - nested/
    - sneaky
    - looper -> ./

这会重复您在我的测试目录中的发现:

$ for apath in ../**/sneaky; do echo "$apath"; done   
../test/nested/looper/sneaky                                                                                                                                                                 
../test/nested/sneaky
../test/sneaky

$ printf "%s\n" ../** | grep sneaky
../test/nested/sneaky
../test/sneaky

在第一个示例中,glob 扩展为(test/nested/looper, test/nested, test),在没有跟随链接的情况下停止,looper因为 glob 后面跟着一个/

然后我们附加/sneaky到它,得到集合(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 后面没有跟随一个时也会抓取文件/

相关内容