在 `zsh` 中对目录进行分组

在 `zsh` 中对目录进行分组

使用zsh这两个命令会产生相同的结果:

ls (dir1|dir2)/dir3/*.txt
ls {dir1,dir2}/dir3/*.txt

仅使用bash以下作品:

ls {dir1,dir2}/dir3/*.txt

那么,如果我想列出.txt多个特定目录中的所有文件,使用zsh上述选项之一是首选还是正确?或者,它们是否等效并且zsh仅提供 中缺少的正则表达式功能bash

答案1

您很可能应该选择第一个版本。

(...)是一个全局运算符,旨在生成文件名, while {...},称为大括号扩展,旨在生成字符串。在许多情况下,您可以在它们之间切换并获得相同的结果,因为文件名是字符串,但几乎没有什么区别。例如,考虑一个目录不存在,在这种情况下你会得到

$ ls (dir1|fakedir)/dir3/*.txt
dir1/dir3/file.txt

$ ls {dir1,fakedir}/dir3/*.txt
zsh: no matches found: fakedir/dir3/*.txt

也许您想要第一个结果。重要的是,第二种情况的错误不是来自大括号扩展,而是来自*!如果您删除它,ls (dir1|dir1)/dir3ls声称它无法访问fakedir/dir3,因此错误是不可预测的(取决于其他内容)。

另一个区别是,第一个版本在重复目录的情况下仅产生一个输出,而第二个版本仅输出多次相同的输出:

$ ls (dir1|dir1)/dir3/*.txt
dir1/dir3/file.txt

$ ls {dir1,dir1}/dir3/*.txt
dir1/dir3/file.txt  dir1/dir3/file.txt

同样,我相信在大多数情况下用户想要第一个结果。

如果您想完全控制通配机制,我建议您熟悉全局限定符(看man zshexpn)。


如果是bash这样,最好设置extglob选项,让您可以访问更多的全局变量,虽然不如 强大zsh,但仍然比大括号扩展更好。

zsh具体来说, s (foo|bar)in的等价物bash -O extglob@(foo|bar)(该语法来自 ksh)。

相关内容