我在 shell 脚本中有几行,其功能是迭代目录、匹配一些名称并删除它们。文件系统的某些区域受到写保护,并且我想保留这些,但将提示或错误的其他一些指示重定向到日志中当他们遇到时。
在脚本中的该点使用rm -r /path/to/directory
会导致脚本输出
rm: descend into write-protected directory /path/to/directory/subdirectory?
因此,当它留给自己的设备时,它会挂起并[最终]超时。
我尝试通过用管道将“n”传递到该提示来纠正此行为
yes n | rm -rv /path/to/directory
这会产生两个不希望的结果:
- 输出
yes: standard output: Broken pipe; yes: write error
每个目录是删除了,并且 - 不将
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