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

Olo*_*rin 5 bash wildcards

这篇 Ask Ubuntu 帖子PATH中,我使用 globstar 在未设置时定位文件:

$ 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
Run Code Online (Sandbox Code Playgroud)

现在想来,这个输出似乎有点奇怪。/usr/bin/X11是一个符号链接/usr/bin

$ readlink /usr/bin/X11
.
Run Code Online (Sandbox Code Playgroud)

因此,那里有X11s 的无限递归,但只有第一个出现在输出中。奇怪的是, just a根本/usr/**没有下降到:X11

$ printf "%s\n" /usr/bin/** | grep X11
/usr/bin/X11
Run Code Online (Sandbox Code Playgroud)

如何协调第一个和最后一个输出?


来自评论:

我在 Ubuntu 16.04 上使用 Bash 版本 4.4.18(1)。

cun*_*mp3 3

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

\n\n

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

\n\n

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

\n\n
\n

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

\n
\n\n

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

\n\n
$ mkdir -p test/nested\n$ cd test\n$ touch sneaky\n$ touch nested/sneaky\n$ cd nested\n$ ln -s . looper\n$ cd ..\n
Run Code Online (Sandbox Code Playgroud)\n\n

产生这样的目录结构:

\n\n
test/\n  - sneaky\n  - nested/\n    - sneaky\n    - looper -> ./\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
$ for apath in ../**/sneaky; do echo "$apath"; done   \n../test/nested/looper/sneaky                                                                                                                                                                 \n../test/nested/sneaky\n../test/sneaky\n\n$ printf "%s\\n" ../** | grep sneaky\n../test/nested/sneaky\n../test/sneaky\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

然后我们附加/sneaky到它,得到集合(test/nested/looper/sneaky, test/nested/sneaky, test/sneaky)

\n\n

在第二个示例中,glob 扩展为(test/nested/looper, test/nested/sneaky, test/nested, test/sneaky, test)(您可以通过删除 来验证| grep sneaky

\n\n

同样,此扩展不会遵循looper链接,但在这种情况下,我们不会附加/sneaky到它,从而../test/nested/looper/sneaky从我们的结果中删除。

\n\n

另一方面,我们继续得到../test/nested/sneaky和 ,../test/sneaky因为当 glob 后面没有跟随一个时,它也会抓取文件。/

\n