我想删除当前目录树中的所有文件,除了save. 我运行了这个命令:
find . \( -name save -prune \) -o -type f -ls | grep /save/
Run Code Online (Sandbox Code Playgroud)
它没有找到。但是当我运行这个命令时:
find . \( -name save -prune \) -o -type f -delete
Run Code Online (Sandbox Code Playgroud)
/save/ 中的所有文件都消失了。我错过了什么?
Sté*_*las 27
-delete意味着-depth这不适用于-prune(-depth从叶子开始)。在 GNU 版本的手册中对此有一个警告(-delete现在 GNUfind和其他一些实现也支持 FreeBSD 扩展)。
info -- find -delete
Run Code Online (Sandbox Code Playgroud)
在命令行上使用“-delete”操作会自动打开“-depth”选项(*note find Expressions::)。如果您之前只是使用“-print”进行测试,这可能会令人惊讶,因此通常最好记住明确使用“-depth”。
info -- find -prune
Run Code Online (Sandbox Code Playgroud)
因为“-delete”意味着“-depth”,将“-prune”与“-delete”结合使用很可能会导致删除的文件比预期的多。
在这里,您可以选择使用rm:
find . -name save -prune -o -type f -exec rm -f {} +
Run Code Online (Sandbox Code Playgroud)
(如果那里有其他人可写的目录,则可能不安全,因为在运行该命令时,可以通过用符号链接替换目录来删除当前目录树之外的文件)。
更安全的选择:
find . -name save -prune -o -type f -execdir rm -f -- {} \;
Run Code Online (Sandbox Code Playgroud)
那没有上面提到的问题,但意味着rm每个文件运行一个。在--对FreeBSD的实现,而不是GNU一个前缀的文件名与是必要的./。
或者,正如科斯塔斯所建议的那样:
LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete
Run Code Online (Sandbox Code Playgroud)
(但这仍然不必要地下降到save目录中)
该LC_ALL=C是有这么*任何字节序列(即使是那些没有在当前区域形成有效的字符)相匹配。请注意,它会影响错误消息的语言(英语而不是用户的语言)。