使用zsh,在选择不适合的模式rm时,甚至在重定向输出时,我都会收到“未找到匹配项”消息。
# rm * > /dev/zero 2>&1
zsh: no matches found: *
Run Code Online (Sandbox Code Playgroud)
我怎样才能摆脱这个消息?
Ste*_*itt 72
此行为由 Zsh 的nomatchoption控制。默认情况下,如果命令行包含不匹配任何内容的 globbing 表达式,Zsh 将打印您看到的错误消息,并且根本不运行该命令。您可以通过运行来禁用它
setopt +o nomatch
Run Code Online (Sandbox Code Playgroud)
然后,不匹配任何内容的通配表达式将保持原样,您将收到一条错误消息rm(您可以禁用 using -f,尽管这是一个坏主意,因为它会在其他情况下强制删除您可能不会想要)。
Sté*_*las 15
你希望它做什么?根本不运行rm(1)?*像在其他类似 Bourne 的 shell (2) 中一样使用文字参数运行它?完全不带参数地运行它 (3)?
files=(*(N)); (($#files)) && rm -- $files. 或者,(rm -- *) 2> /dev/null但这也会隐藏真正的错误,rm这将是愚蠢的。您可以丢弃zsh错误,但可以使用以下rm命令恢复命令的stderr(rm -- * 2>&3 3>&-) 3>&2 2> /dev/nullemulate sh -c 'rm -- *' 2> /dev/null. 然后像在sh其zsh现在模拟为单个命令行中,非匹配*原样传递是rm和rm抱怨作为*文件不存在。我们抑制rm的 stderr 就像您在sh抑制该错误消息时所做的那样,但同样,这很愚蠢,因为它会隐藏真正的错误,rm而不是sh将文字传递*给rm. rm -f '*'不会抱怨一个不存在的*文件,所以你可以这样做emulate sh -c 'rm -f -- *'rm -- *(N). rm虽然在没有通过任何参数时会抱怨,但同样,不是rm -f: rm -f -- *(N)。通常,rm -f如果您希望所有文件都消失,并且仅在无法删除文件或rm返回后 IOW 仍然存在时才会出现错误,则是您要使用的命令。您通常还希望-f在脚本中使用以避免在某些情况下提示用户。
在这里,rm当 glob 不匹配时调用是错误的。在sh1层的行为是错误的。对于像这样的模式是无害的*,但是对于像 那样的模式,当它不匹配时按原样*.[ch]传递*.[ch]可能会导致*.[ch]文件被错误删除:
$ ls
*.[ch] foo.txt
$ zsh -c 'rm *.[ch]'
zsh:1: no matches found: *.[ch]
$ ls
*.[ch] foo.txt
$ sh -c 'rm *.[ch]'
$ ls
foo.txt
Run Code Online (Sandbox Code Playgroud)
与错误而失败是做的最明智的事情,是什么zsh(和fish,csh,tcsh,bash -o failglob和原来的Unix shell)一样。
如果您想照顾自己的特殊情况,zsh可以使用它的(N)glob 限定符(对于noglob),就像上面的情况(1)一样。fish(至少在最近的版本中)使它变得更加容易,因为它为命令做了一个隐式的noglobset。所以,那里的等价物是:
set files *
if count $files > /dev/null
rm -f -- $files
end
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅为什么 nullglob 不是默认值。
1 . 严格来说,这只是sh从 Bourne shell 开始(自 1979 年的 Unix V7 以来);的早期版本sh(确实调用/etc/glob了未加引号的通配符,这是glob名称的来源)确实表现得像cshor zsh -o cshnullglob,也就是说,/etc/glob如果没有任何匹配的glob将中止命令(并且至少会抑制不匹配的 glob其中一个有任何匹配)。Bourne shell破坏了这种行为。
在交互式 zsh 中输入:
setopt no_nomatch
rm * > /dev/null 2>&1
setopt nomatch # `nomatch` is default, see `man zshoptions`
Run Code Online (Sandbox Code Playgroud)
对我来说,nullglob不cshnullglob工作