Globstar is enabled, and the pattern `**/` returns files only inside sub-directories but `**/*` returns files both in root and in sub-directories

huangapple go评论58阅读模式
英文:

Globstar is enabled, and the pattern `**/` returns files only inside sub-directories but `**/*` returns files both in root and in sub-directories

问题

我的文件结构如下所示:

-rw-r--r-- 1 athar 197609 12467 Jun 12 22:33 rootFile1.md
-rw-r--r-- 1 athar 197609   736 Jun  9 17:42 rootFile2.md
-rw-r--r-- 1 athar 197609   662 Jun  9 18:21 rootFile3.md
drwxr-xr-x 1 athar 197609     0 Jun 15 23:58 testfolder/

testfolder/ 包含以下内容:

testfolder:
subDirFile1.md  subDirFile2.md

我已启用了 shopt -s globstar 以启用 globstar。globstar 的文档说明如下(来源):

如果设置了 globstar,用于文件名扩展的模式 '**' 将匹配所有文件和零个或多个目录和子目录。如果模式后跟着 '/',则只匹配目录和子目录。

$ ls **/
subDirFile1.md  subDirFile2.md

根据文档,这是有道理的,因为它只匹配目录和子目录,不匹配文件。然而,

$ ls **/*.md
rootFile1.md  rootFile3.md               testfolder/subDirFile2.md
rootFile2.md  testfolder/subDirFile1.md

上述命令不应该只输出 subDirFiles 吗?因为 ** 后面跟着 '/',根据文档,只匹配目录和子目录。为什么它也匹配了根目录中的文件?

我还应该提到,当我禁用 globstar 时,输出只会搜索子目录。

$ ls **/*.md
testfolder/subDirFile1.md  testfolder/subDirFile2.md
英文:

My file structure looks like this

-rw-r--r-- 1 athar 197609 12467 Jun 12 22:33 rootFile1.md
-rw-r--r-- 1 athar 197609   736 Jun  9 17:42 rootFile2.md
-rw-r--r-- 1 athar 197609   662 Jun  9 18:21 rootFile3.md
drwxr-xr-x 1 athar 197609     0 Jun 15 23:58 testfolder/

with the testfolder/ containing

testfolder:
subDirFile1.md  subDirFile2.md

I've enabled globstar using shopt -s globstar. The documentation of globstar states (source)

If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match.

$ ls **/
subDirFile1.md  subDirFile2.md

This makes sense according to the docs, where it only matches dirs and sub-dirs, not files. However,

$ ls **/*.md
rootFile1.md  rootFile3.md               testfolder/subDirFile2.md
rootFile2.md  testfolder/subDirFile1.md

Shouldn't the above command only output the subDirFiles since ** is followed by / and as per docs, only directories and subdirectories match? Why does it match files in the root as well?

I should also mention that when i disable globstar, the output will only search the sub directory.

$ ls **/*.md
testfolder/subDirFile1.md  testfolder/subDirFile2.md

答案1

得分: 1

man bash

当启用globstar shell选项时,[...]两个相邻的*作为一个模式将匹配所有文件和零个或多个目录和子目录。

您的rootFile1.md确实前面没有任何目录,因此它匹配。

英文:

From man bash:

> When the globstar shell option is enabled, [..] two adjacent *s used as a single pattern will match all files and zero or more directories and subdirectories.

Your rootFile1.md does indeed have zero directories in front, so it matches.

答案2

得分: 0

  • 当启用globstar时:

    • ** 匹配 "所有文件和零个或多个目录和子目录"
    • **/ 不会单独匹配文件,但在其他情况下,它的行为与 ** 相同,意味着它可以匹配零个目录/子目录。
    • *.md 是普通的通配符,可以匹配任何内容。
  • 当将它们组合在一起时,**/*.md 表示 "匹配零个或多个目录/子目录中以 .md 结尾的内容"。因为你的根目录是零个目录深度,所以它也包含在匹配中。

为了完整起见,当禁用globstar时,** 等同于 *,所以 ls **/*.mdls */*.md 是相同的。

如果你的目标是忽略根目录,你可以在模式前面添加 */ 来创建 */**/*.md。前导的 */ 只匹配目录,不会出现匹配 "零个目录" 的问题。

英文:

To officially expand on the existing answer, when globstar is enabled:

  • ** matches "all files and zero or more directories and subdirectories"

  • **/ will not match files on its own, but otherwise it behaves the same as ** meaning it CAN match zero directories/subdirectories.

  • *.md is a plain old glob and can match on anything.

When you put it all together, **/*.md says "match in zero or more directories/subdirectories something ending in .md." Your root directory is zero directories deep, so it's included in the match.

For completeness, when globstar is disabled ** is equivalent to * so ls **/*.md is the same thing as ls */*.md.

If your goal is to ignore the root directory, you can prepend the pattern with */ to create */**/*.md. The leading */ will only match directories and doesn't have the same gotcha of matching on "zero directories".

答案3

得分: 0

我认为这里的混淆部分在于ls本身也会隐式展开目录 - 也就是说,如果您将目录名称作为参数传递,它将列出目录的内容而不是目录本身。这意味着像ls **/这样的输出是两个扩展过程的结果,每个过程都遵循不同的规则。

您可以通过使用set -x来清楚地看到这一点,它使bash在替换和展开完成后打印每个命令:

$ ls **/
+ ls testfolder/
subDirFile1.md    subDirFile2.md

在这里,**/仅展开为当前目录中的目录。它不包括当前目录,这就是为什么rootFile1.md等未列出的原因。

如果有子目录,它包括子目录。让我们创建一个子目录并看看效果:

$ mkdir testfolder/subdir
+ mkdir testfolder/subdir
$ touch testfolder/subdir/subsubfile{1..2}.md
+ touch testfolder/subdir/subsubfile1.md testfolder/subdir/subsubfile2.md

$ ls **/
+ ls testfolder/ testfolder/subdir/
testfolder/:
subDirFile1.md    subDirFile2.md    subdir

testfolder/subdir/:
subsubfile1.md    subsubfile2.md

现在,ls得到了两个目录作为参数,因此它将列表分为不同的部分,以目录为单位,使得更清楚发生了什么。

另一种帮助澄清这一点的方法是使用ls -d,它告诉ls隐式展开目录,因此您只会看到一级展开。

英文:

I think part of the confusion here is that ls itself also implicitly expands directories -- that is, if you pass a directory name as an argument, it lists the contents of the directory rather than the directory itself. This means the output from something like ls **/ is the result of two expansion processes, each of which plays by different rules.

You can see this clearly with set -x, which makes bash print each command after substitutions and expansions have been done:

$ ls **/
+ ls testfolder/
subDirFile1.md	subDirFile2.md

Here, the **/ expands to just the directory that's in the current directory. It does not include the current directory, which is why rootFile1.md etc are not listed.

It would include subdirectories if there were any. Let's create one and see the effect:

$ mkdir testfolder/subdir
+ mkdir testfolder/subdir
$ touch testfolder/subdir/subsubfile{1..2}.md
+ touch testfolder/subdir/subsubfile1.md testfolder/subdir/subsubfile2.md

$ ls **/
+ ls testfolder/ testfolder/subdir/
testfolder/:
subDirFile1.md	subDirFile2.md	subdir

testfolder/subdir/:
subsubfile1.md	subsubfile2.md

Now ls got two directories as arguments, so it breaks the listing into sections by directory, making it clearer what's going on.

Another way to help clarify this is to use ls -d, which tells ls not to implicitly expand directories, so you only see one level of expansion happening.

huangapple
  • 本文由 发表于 2023年6月16日 02:42:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76484629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定