ls 忽略“没有匹配项”

Jon*_*son 11 ls bash zsh shell-script wildcards

我想列出的所有文件的文件夹,名为中foldername有扩展testatestbtest

我的直接想法是跑 ls ./foldername/*.{a,b,}test

这工作正常,除非扩展名没有任何内容atest,在这种情况下我会收到错误消息zsh: no matches found: ./foldername/*.atest

有什么办法可以简单地忽略此错误并打印确实存在的文件?

我需要它在 ZSH 和 BASH 中工作。

Sté*_*las 12

ls -d ./foldername/*.{a,b,}test
Run Code Online (Sandbox Code Playgroud)

{a,b,...} 不是 glob 运算符,这是大括号扩展,首先扩展为:

ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test
Run Code Online (Sandbox Code Playgroud)

并且每个 glob 都单独展开,如果任何 glob 不匹配,则该命令将如您所期望的那样取消zsh(或fish; in bash,您需要failglob获得类似行为的选项)。

在这里,您希望使用一个匹配所有这些文件的 glob,并且只有在该 glob 与任何文件都不匹配时才取消该命令:

ls -d ./foldername/*.(a|b|)test
Run Code Online (Sandbox Code Playgroud)

您不想使用nullglob,就好像没有匹配的 glob 一样,它会在ls没有参数的情况下运行,因此请列出当前目录。cshnullglob在这方面更好,因为它删除了不匹配的 globs 但如果所有 globs 都无法匹配,它仍然会取消命令。

您不会想要使用nonomatch,因为这会给您带来糟糕的行为,bash这将是一种耻辱。

对于同时适用于zshand的 glob 替代方案bash,您可以使用 ksh globs(set -o kshglobinzshshopt -s extglobin bash)。

然后,你会这样做:

ls -d ./foldername/*.@(a|b|)test
Run Code Online (Sandbox Code Playgroud)

或者:

ls -d ./foldername/*.?([ab])test
Run Code Online (Sandbox Code Playgroud)

添加failglob选项bash以避免 glob 在ls不匹配时按字面传递。

请参阅为什么 nullglob 不是默认值?想要查询更多的信息。


Joh*_*oon 11

最好这样做find

find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
Run Code Online (Sandbox Code Playgroud)

  • @JeffSchaller,请注意`-maxdepth` 是GNU 扩展。注意与 globs 的 3 个其他差异:`find` 将包括隐藏文件,不对列表进行排序,并且无法匹配包含未形成有效字符的字节的文件名(如 UTF-8 中的 `$'St\xe9phane.atest'`地区) (4认同)