Bash compgen没有正确解析通配符



我的目标是列出所有与foo/**匹配的文件,而此文件夹包含文件(1和2)和子目录(bar),其中包含文件:

foo/
├── 1
└── bar
└── 2

Bash有一个内置的compgen。我在这个答案中发现了这个函数。使用compgen -G <pattern>,在我的情况下,compgen -G 'foo/**'应该列出所有文件和文件夹。但是,它只打印第一个文件夹(foo)的内容:

foo/bar
foo/1

foo/bar/2不见了!我希望得到以下输出:

foo/bar
foo/1
foo/bar/2

这是bash的compgen中的错误还是glob不正确?


做更多实验
$ compgen -G 'foo/**/*'
foo/bar/2

使用Python3的pathlib.Path.glob:

from pathlib import Path
p=Path(".").resolve()
[print(f) for f in p.glob("foo/**")]

输出:

foo
foo/bar

from pathlib import Path
p=Path(".").resolve()
[print(f) for f in p.glob("foo/**/*")]

输出:

foo/1
foo/bar
foo/bar/2

这个版本正是我想要的,但是,我更喜欢最小化依赖关系,根本不使用Python(只使用bash)。


  • Bash version 5.0.17(1)-release (x86_64-pc-linux-gnu) on Ubuntu 20.04.
  • Bash globstar选项打开/关闭不会改变任何东西
  • Python 3.6.9

compgen是一个专门用于生成补全的工具。它确实看起来有bug(因为它不支持globstar选项),但它也不是用来生成匹配glob的文件列表的最佳工具;因此,没有真正的实际理由让这个bug成为任何人关心的问题。

最好的工具是glob表达式。

shopt -s extglob nullglob
files=( foo/** ) # store files matching foo/** in an array
echo "Found ${#files[@]} files:"
printf ' - %qn' "${files[@]}"

如果在您的实际环境中,您希望获得从变量展开的glob表达式,并且只有执行globb并抑制字符串分割,那么您需要在执行files=( $glob )赋值时临时将IFS设置为空值。

相关内容

  • 没有找到相关文章

最新更新