为什么 find with -delete 会删除我的 /save/ 目录中的文件,而 find without delete 却无法找到它们?

为什么 find with -delete 会删除我的 /save/ 目录中的文件,而 find without delete 却无法找到它们?

我想删除当前目录树中的所有文件,除了save.我运行了这个命令:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

结果什么也没有找到。但是当我运行这个命令时:

 find . \( -name save -prune \) -o -type f -delete

/save/ 中的所有文件都消失了。我缺少什么?

答案1

-delete意味着-depth不适用于-prune-depth从叶子开始)。 GNU 版本的手册中对此有一个警告(这是一个 FreeBSD 扩展,现在也受到 GNU和其他一些实现-delete的支持)。find

info -- find -delete

在命令行上使用“-delete”操作会自动打开“-深度”选项(*注意查找表达式::)。如果您之前只是使用“-print”进行测试,这可能会令人惊讶,因此通常最好记住明确使用“-深度”。

info -- find -prune

因为“-delete”意味着“-深度”,所以将“-prune”与“-delete”结合使用很可能会导致删除比您预期更多的文件。

在这里,您可以选择使用rm

find . -name save -prune -o -type f -exec rm -f {} +

(可能不安全如果那里有其他人可写的目录,因为在运行该命令时,可以通过用符号链接替换目录来删除当前目录树之外的文件)。

更安全的替代方案:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

这没有上面提到的问题,但意味着rm每个文件运行一个。这--是 FreeBSD 实现所必需的,而不是 GNU 实现所必需的./

或者,正如科斯塔斯建议的那样:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(但这仍然不必要地下降到save目录中)

那里LC_ALL=C所以*匹配任何字节序列(即使是那些在当前语言环境中不形成有效字符的字节序列)。请注意,它会影响错误消息的语言(英语而不是用户的语言)。

相关内容