Pet*_*nak 5 zsh wildcards brace-expansion
在bash
我可以使用花括号来模式匹配多个文件,例如
ls *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
如果没有特定扩展名的文件,我会收到警告,但会列出其余文件。
ls: 无法访问 '*.err': 没有那个文件或目录
但是,在zsh
我得到一个错误并且没有为现有文件产生输出。
zsh:未找到匹配项:*.err
这也适用于删除,在尝试删除文件时:
rm -f *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
将在bash
没有任何错误或警告的情况下删除所有匹配的文件,但zsh
它会出错并且根本不会删除任何内容。
有没有办法使zsh
行为与 相同bash
,或者是否有另一种方法可以轻松删除/列出现有文件¹?
¹显然我可以做类似的事情,find . -name '*.dot' -or -name '*.svg' -or -name '.err' | xargs rm
但这并不是特别容易/实用。
Sté*_*las 13
你没有得到的警告bash
,你会得到一个错误的ls
(你会发现,ls
退出状态非0,表示它已失败)。
在zsh
and 中bash
, ,{...}
都不是通配符,而是在通配符之前发生的扩展。
在:
ls -d -- *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
(你忘记了-d
和--
btw),shell 扩展了{...}
第一个:
ls -d -- *.dot *.svg *.err
Run Code Online (Sandbox Code Playgroud)
然后做 glob。bash
像大多数 Bourne-like shell 一样,不匹配的 glob 按原样传递。在 on 时zsh
,不匹配的 glob 是一个错误。
了解如何rm -f [ab].c
在bash
可以删除该[ab].c
文件,如果没有所谓的文件a.c
也没有b.c
。在 中zsh
,你会得到一个不匹配的错误。请参阅 中的failglob
选项bash
以获得类似的行为。
ls -d -- *.{dot,svg,err}(N)
Run Code Online (Sandbox Code Playgroud)
inzsh
将nullglob
在所有 3 个 glob 上启用该选项,以便如果 glob 不匹配,它们将被删除,但这可能不是您想要的,因为如果没有一个 glob 与任何文件匹配,则命令将变为:
ls -d --
Run Code Online (Sandbox Code Playgroud)
哪个会列出 .
(当前目录)。
最好的方法是使用一个匹配具有 3 个扩展名之一的文件的 glob:
ls -d -- *.(dot|svg|err)
Run Code Online (Sandbox Code Playgroud)
这将给出一个排序的文件列表,除非没有找到与该模式匹配的文件ls
,ls
否则将运行。
您还可以选择使用或启用sh
/ bash
(伪造的 IMO)行为。稍微好一点的方法是启用该行为(这也是 Bourne shell 发布之前 Unix shell 的行为):emulate sh
unsetopt nomatch
csh
setopt cshnullglob
Run Code Online (Sandbox Code Playgroud)
使用该选项,仅当命令行上的所有glob都无法匹配时,才会取消该命令。如果至少有一个匹配,则删除所有不匹配的,因此:
ls -d -- *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
将扩展dot
,svg
和err
依次省略缺失的。
如果您想比较不同方法的参数顺序的影响,您需要一个命令(与 相反ls
)在显示之前不对它们进行排序。使用 GNU ls
,您可以-U
为此传递选项,或者因为ls
只在此处打印其参数,只需使用即可printf '%s\n' *...
。