Bash compgen 没有正确解析通配符
Bash compgen not parsing wildcard correctly
我的目标是列出与 foo/**
匹配的所有文件,而此文件夹包含文件(1 和 2)和子目录 (bar),文件为:
foo/
├── 1
└── bar
└── 2
Bash 有一个名为 compgen
的内置函数。我发现了这个函数 in this answer。使用 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 版本 5.0.17(1)-发布 (x86_64-pc-linux-gnu) Ubuntu 20.04.
- Bash globstar 选项 on/off 没有任何改变
- Python 3.6.9
compgen
是一个专门用于生成补全的工具。它 似乎有问题(因为它不支持 globstar
选项),但它也不是用于生成匹配文件列表的最佳工具全球;所以没有真正实际的理由让这个错误成为任何人关心的错误。
最好的工具就是 glob 表达式。
shopt -s extglob nullglob
files=( foo/** ) # store files matching foo/** in an array
echo "Found ${#files[@]} files:"
printf ' - %q\n' "${files[@]}"
如果在您的 real-world 环境中您想要从变量扩展 glob 表达式,并且 仅 执行 globbing 并抑制 string-splitting,那么您希望在执行 files=( $glob )
赋值时临时将 IFS
设置为空值。
我的目标是列出与 foo/**
匹配的所有文件,而此文件夹包含文件(1 和 2)和子目录 (bar),文件为:
foo/
├── 1
└── bar
└── 2
Bash 有一个名为 compgen
的内置函数。我发现了这个函数 in this answer。使用 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 版本 5.0.17(1)-发布 (x86_64-pc-linux-gnu) Ubuntu 20.04.
- Bash globstar 选项 on/off 没有任何改变
- Python 3.6.9
compgen
是一个专门用于生成补全的工具。它 似乎有问题(因为它不支持 globstar
选项),但它也不是用于生成匹配文件列表的最佳工具全球;所以没有真正实际的理由让这个错误成为任何人关心的错误。
最好的工具就是 glob 表达式。
shopt -s extglob nullglob
files=( foo/** ) # store files matching foo/** in an array
echo "Found ${#files[@]} files:"
printf ' - %q\n' "${files[@]}"
如果在您的 real-world 环境中您想要从变量扩展 glob 表达式,并且 仅 执行 globbing 并抑制 string-splitting,那么您希望在执行 files=( $glob )
赋值时临时将 IFS
设置为空值。