运行“ rm *”时如何摆脱“找不到匹配项”


22

使用zsh,当选择不适合的模式rm甚至重定向输出时,都会收到“找不到匹配项”消息。

# rm * > /dev/zero 2>&1
  zsh: no matches found: *

我如何摆脱此消息?


您是否要删除当前目录中的所有内容?当前目录是什么?
cutrightjm

您可以使用setopt extended_glob(甚至是简单使用rm * >/dev/null 2>&1),但实际上您应该做出不需要的解决方法rm *,这绝对是危险的
恶心的

你确实应该下沉/dev/null而不是dev/zero。另外,您的stderr重定向缺少&;应该是2>&1
roaima

该错误消息是zsh在评估命令期间而不是在命令本身的运行时生成的(由于错误,该命令甚至没有运行)。此处的输出重定向只会影响命令的输出,而不会影响Shell本身。
阿达芬

Answers:


42

此行为由Zsh的nomatchoption控制。默认情况下,如果命令行包含不匹配任何内容的全局表达式,则Zsh将打印您看到的错误消息,并且根本不运行命令。您可以通过运行禁用它

setopt +o nomatch

然后,不匹配任何内容的表达式将按原样保留,并且您会收到一条错误消息rm(您可以禁用使用-f,尽管这是一个坏主意,因为在其他情况下您可能会强制删除它们想要)。


4
该行为也由nullglobcshnullglob选项控制。如果nullglob设置为if 并且找不到匹配的文件,则将模式从参数列表中删除,而不是生成错误。cshnullglob除非命令中的所有模式都不匹配,否则设置具有相似的效果,在这种情况下将报告错误。注意:设置nullglobcshnullglob覆盖nomatch。您还可以nullglob通过使用glob限定符设置单个模式Nrm *(N)
Adaephon

nomatch并不理想,这就是像伯恩的贝壳那样。如果模式不匹配,则将其原样传递给rm(!),这rm将产生错误,或者更糟的是,可能会删除*.[ch]例如模式的错误文件!
斯特凡Chazelas

9

您要它做什么呢?根本不运行rm(1)?与*其他类似Bourne的shell(2)中一样,使用文字参数来运行它吗?完全不带参数运行(3)?

  1. files=(*(N)); (($#files)) && rm -- $files。或者,(rm -- *) 2> /dev/null但这也将隐藏真正的错误,rm而这将是愚蠢的。您可以丢弃zsh错误,但可以通过以下rm命令恢复命令的stderr(rm -- * 2>&3 3>&-) 3>&2 2> /dev/null
  2. emulate sh -c 'rm -- *' 2> /dev/null。然后像在shzsh现在模拟为单个命令行中,非匹配*原样传递是rmrm抱怨作为*文件不存在。我们抑制了rmstderr,就像sh抑制该错误消息一样,但是这又很愚蠢,因为它将隐藏真正的错误,rm,而不是通过的不当行为引起的误差sh通过文字*rmrm -f '*'不会抱怨*文件不存在,所以您可以emulate sh -c 'rm -f -- *'
  3. rm -- *(N)rm可能会抱怨,尽管没有传递任何参数,但不是rm -frm -f -- *(N)

通常,rm -f如果您希望所有文件都消失,并且仅在无法删除文件或rm返回后IOW仍然存在的情况下才会出现错误,则是您要使用的命令。您通常也想使用-f在脚本中,以避免在某些情况下提示用户。

在这里,rm当全局不匹配时调用是错误的。在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

与错误而失败是做的最明智的事情,是什么zsh(和fishcshtcshbash -o failglob和原来的Unix shell)一样。

而且,如果您想保管这种特殊情况,zsh可以像上面的情况(1)一样,使用其(N)glob限定符(对于noglob)使其变得容易。fish(至少在最新版本中),因为它执行隐式的noglob使其更加容易set命令。因此,等效项为:

set files *
if count $files > /dev/null
  rm -f -- $files
end

请参阅为什么nullglob不是默认值更多详细信息,。


1。严格来说,这只是sh自Bourne shell以来(自1979年Unix V7起)。的早期版本sh(确实调用/etc/glob了无引号的通配符,这是通配符名称所来自的地方)的行为类似cshzsh -o cshnullglob/etc/glob如果所有通配符都不匹配,它将中止命令(并且至少抑制不通配的通配符)其中之一有任何比赛)。该行为被Bourne外壳破坏了。


我认为他希望从而rm不是从外壳程序中获取错误消息。诸如“ rm:无法删除'*':没有这样的文件或目录”之类的东西。
伊曼纽尔

@Emmanuel,那就是2:emulate sh -c 'rm -- *'得到Bourne shell的(buggy IMO)行为。
斯特凡Chazelas

@Stephane_Chazelas如其所写,2是他没有问过的问题的正确答案:)。
伊曼纽尔

@Emmanuel,所有3个人回答问题:如何摆脱“ No match”错误。OP的代码可消除rm错误。在没有匹配文件的情况下,您可以在其他Shell中执行此操作以抑制错误,并且也导致真正的rm错误得到抑制。我的回答概述了这一点,并希望显示出zsh行为是如何更好的。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.