如果文件不存在,如何使rm不给出错误?


285

我正在编写一个makefile,它将在编译结束时清理一些无用的文件。如果已经制作了目标,它当然会跳过该目标,并且可能不存在无用文件。所以,如果我这样做:

rm lexer.ml interpparse.ml interpparse.mli

我可能会收到错误,因为其中一个文件不存在。有什么方法可以说 rm 忽略这些文件?

在阅读手册页时,我看到以下选项:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

听起来像 几乎 我想要什么,但我不确定权限部分。有没有办法做到这一点?


你试过一些吗? rm 在沙盒中?看起来像 -f 完全符合你的要求,不管是什么样的。
JMD

如果权限不允许,rm将与 -f 选项仍然尝试删除它。它会失败。它不会告诉你它失败了。如果文件名是变量或glob,则很有用。
LawrenceC

Answers:


239

-f 选项肯定是你想要使用的。

它引用的文件权限的确认是这样的:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

所以 rm 如果您尝试删除没有写入权限的文件,则会发出警告。如果您对目录具有写权限但允许这有点奇怪,则允许这样做 rm 通常会警告你。


1
大多数但不是所有系统都会问(我认为)。有些要求 -i
DaveParillo

1
如果您想要错误消息,而不是错误退出代码,请参阅答案 吉尔伯克斯 。我用 set -e 在我的所有bash脚本中,以便在任何命令发出错误后退出脚本。我经常想要一个脚本告诉我是否 rm 给出了一个错误,但无论如何都要继续。继续。
cledoux

97

另一个解决方案就是这个: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

只需在命令后添加一个OR语句:

rm -rf my/dir || true

这样,当语句#1失败(抛出错误)时,运行语句#2,这很简单 true


1
它打印错误并继续执行,这是我的情况所需要的。
worldsayshi

4
要不就 rm -rf my/dir ||: 更简洁( : 是的缩写 true
Godsmith

我认为更好的解决方案。它很容易看到发生了什么以及为什么忽略结果代码。我喜欢!
Mavamaarten

73

我迟到了,但我一直都在使用这个。在makefile中,添加 - 到一行的开头,忽略该行的返回值。像这样:

-rm lexer.ml interpparse.ml interpparse.mli

9
这仍然会向控制台输出错误,它会训练你忽略make输出中的错误,这可能不是你想要的。在我看来,rm -rf是一个更好的选择。
Godsmith

@Godsmith我宁愿忽略错误而不是强制递归删除。这可能非常顽皮。并且为makefile特定语法+1
Daishi

如果rm -rf可能是“顽皮”,则意味着您在版本控制下的目录外使用make。为什么?
Godsmith

请提供文档链接。可以找到此功能的说明。
George Sovetov


10

如果您不想使用-f选项,则替代方法是:

rm filethatdoesntexist 2> /dev/null 

这样可以防止错误打印。


5
不幸的是,这仍然会给出错误退出代码。
Shaun McDonald

7

如果你找到了一些方法 glob的 文件名, rm 如果找不到比赛,我们不会抱怨。所以像 lexer.m* interpparse.*等等应该适合你(当然,小心你不要删除太多)。也, -f 是一种非常合理的方式,只要您不希望文件权限可以避免删除您不想删除的文件 - 如果您不想删除它,请不要将其放入名单。


由于存在一个我不想删除的lexer.mll文件,因此无法实现全局操作。谢谢你说明为什么-f是合理的。我想在经过太多误导之后我会过于谨慎 sudo rm -rf
Jason Baker

甚至没有更严格的限制 lexer.m? ...?那会抓住 lexer.mllexer.mz, 但不是 lexer.mll 要么 lexer.mla
JMD

1
@JMD:我想这取决于你的shell以及它为globbing提供的模式匹配支持。
Nick Bastin

5

-f选项表示如果某些内容不符合预期,则不会提示您。这并不意味着不考虑权限。

如果您没有足够的权限删除文件,则不会删除该文件。

,如果您有足够的权限更改权限,您的文件将被删除。如果您是拥有readonly权限的文件的所有者(-r --------),则会出现这种情况。作为所有者,您可以 chmod u+w,然后删除它: rm -f 将删除该文件。


3

也许可以帮助类似的线:

touch fakefile.exe fakefile.o && rm *.o *.exe

我知道这不是很聪明,但它确实起到了作用。


2

替代:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

太糟糕的Makefile不能跨行共享shell函数定义。


您是否尝试在行尾使用\(反斜杠)让它继续下一行?
some

@some:是的,它们可以分布在多行中,但要在配方中共享它们,您必须将定义放在make变量中。
reinierpost

2

这是我在shell脚本中使用的内容。它隐藏了错误消息和错误代码。

rm doesnotexist 2> /dev/null || echo > /dev/null

0

您可以在他们之前触摸文件。 如果它们不存在会创建它们:-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli

0

rm -rf ppp>/dev/null 2>&1 你更新得到错误消息问题发生,如果错误产生不是STDERR 2而是STDOUT 1 ...当命令生成不是错误但警告时发生。 您需要设置过滤器并删除此消息。但这种情况很普通。


0

测试以查看文件是否首先存在,如果存在,则将其传递给rm。然后来自rm的错误将是有意义的。 -f或忽略错误消息通常比人们想要的更具包容性。 -f可能会做你不想做的事情。

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

如果您想确定存在更多文件,请添加更多测试子句。

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.