Shell 脚本 `rm -r`:重定向写保护提示并回答“n”

Shell 脚本 `rm -r`:重定向写保护提示并回答“n”

我在 shell 脚本中有几行,其功能是迭代目录、匹配一些名称并删除它们。文件系统的某些区域受到写保护,并且我想保留这些,但将提示或错误的其他一些指示重定向到日志中当他们遇到时。

在脚本中的该点使用rm -r /path/to/directory会导致脚本输出

rm: descend into write-protected directory /path/to/directory/subdirectory?

因此,当它留给自己的设备时,它会挂起并[最终]超时。

我尝试通过用管道将“n”传递到该提示来纠正此行为

yes n | rm -rv /path/to/directory

这会产生两个不希望的结果:

  1. 输出yes: standard output: Broken pipe; yes: write error每个目录删除了,并且
  2. 不将rm: descend into write-protected...消息返回到标准输出。

这样做的正确方法是什么?

更新: 根据 @roaima 的说法,我实际上根本没有yes n通过管道传输提示,因为该管道的存在使得rm非交互式。这很讽刺,因为我实际上只是为了获得一些输出而利用交互性,但如果我关闭交互性,程序就会错误退出。我不想忽略该错误(例如,通过附加,|| true因为我在 SE 上看到了很多其他地方),因为我想要受保护文件的名称。

答案1

rm如果 stdin 是终端,将要求确认不可写目标。-i另一方面,该标志打开确认全部目标。显然,这两种方法都不适用于管道yes n到 的简单解决方案rm,因此我们必须使用其他方法。

使用 GNU find,删除至少设置了一个写入模式位的所有对象(像往常一样,首先使用-print而不是-delete首先进行测试):

find dir/ -perm /0222 -delete

或者,删除至少设置了一个写入模式位的所有文件(*) ,但跳过不可写目录的内容:

find . -type d ! -perm /0222 -prune -o ! -type d -perm /0222 -exec rm {} + 

(* 实际上除了目录之外的所有内容)

-delete意味着深度优先搜索(至少在 GNU find 上),并且不适用于-prune,所以我们不能在这里使用它。之后我们可以删除空的可写目录:

find . -type d -perm /0222 -delete

对于非空目录这将引发错误。

-perm /0222代表“任何写入位均已设置”,其反义词! -perm /0222为“未设置任何写入位”。

在其他版本的 find 中,使用+0222代替/0222. (根据 GNU 手册页,前者与 POSIX 要求冲突,已被弃用。)


要查找不可写的文件和目录,我们可以类似地使用

find . ! -perm /0222 

递归地列出不可写目录的内容有点困难,但使用 GNU 工具这可能会起作用:

find . ! -perm /0222 -print0 | xargs -0 find 

答案2

我建议考虑使用不同的工具。 “查找”命令非常强大,一旦您克服了一些语法规则,就很容易使用。

例子:

查找/目录-名称模式-perm g = w -exec / bin / rm {} \;

这将搜索 /directory 下具有“write”组权限的所有文件和子文件夹(逻辑匹配 0020 八进制 chmod 格式),然后删除该文件。

或者您可以使用打印选项运行它并获取与查找模式匹配的文件的列表。

例如:查找/目录-名称模式-perm 0111-print

相关内容