繁体   English   中英

如何递归删除某种类型的文件

[英]How to Recursively Remove Files of a Certain Type

我误读了gzip文档,现在我必须从许多目录中删除大量的“.gz”文件。 我尝试使用'find'来查找所有.gz文件。 但是,只要名称中有空格的文件,rm就会将其解释为另一个文件。 只要有破折号,rm就会将其解释为新旗帜。 我决定用'sed'用“\\”代替空格,用空格破坏用“\\ - ”代替,这就是我想出来的。

find . -type f -name '*.gz' | sed -r 's/\ /\\ /g' | sed -r 's/\ -/ \\-/g'

当我在一个文件上运行find / sed查询时,例如,其名称为“Test - File - for - show.gz”,我得到了输出

./Test\ \-\ File\ \-\ for\ \-\ show.gz

这对于rm来说似乎是可以接受的,但是当我跑步时

rm $(find . -type f -name '*.gz'...)

我明白了

rm: cannot remove './Test\\': No such file or directory
rm: cannot remove '\\-\\': No such file or directory
rm: cannot remove 'File\\': No such file or directory
rm: cannot remove '\\-\\': No such file or directory
...

我没有广泛使用sed,所以我不得不假设我在使用正则表达式做错了。 如果你知道我做错了什么,或者你有更好的解决方案,请告诉我。

在空格之前添加反斜杠可以保护空间免受shell源代码中的扩展。 但是命令替换中的命令输出不进行shell解析,只进行通配符扩展和字段拆分。 在空格之前添加反斜杠不会保护它们免受字段拆分。

在破折号之前添加反斜杠是完全无用的,因为它是将破折号解释为特殊的rm ,并且它不会将反斜杠解释为特殊的。

find的输出通常是不明确的 - 文件名可以包含换行符,因此您不能使用换行符作为文件名分隔符。 除非你在一个已知的,受限制的字符集中处理文件名,否则解析find的输出通常会被破坏,而且它通常不是最简单的方法。

find有一个内置的方法来执行外部程序: -exec action。 没有进行解析,因此文件名中的特殊字符不会出现任何问题。 (以-开头的路径仍然可以解释为一个选项,但所有路径都以.开头.因为那是遍历的目录。)

find . -type f -name '*.gz' -exec rm {} +

许多find实现(Linux,Cygwin,BSD)可以在不调用外部实用程序的情况下删除文件:

find . -type f -name '*.gz' -delete

请参阅为什么我的shell脚本会在空格或其他特殊字符上出现问题? 有关编写健壮的shell脚本的更多信息。

没有必要管道到sed等。相反,你可以在find上使用-exec标志,它允许你对命令的每一个结果执行一个命令。

例如,对于您的情况,这将工作:

find . -type f -name '*.gz' -exec rm {} \;

大致相同:

find . -type f -name '*.gz' -exec rm {} +

最后一个没有为每个结果打开子shell,这使得它更快。


man find

-exec命令;

执行命令; 如果返回0状态,则返回true。 以下所有要查找的参数都被视为命令的参数,直到参数组成为;' is encountered. The string ;' is encountered. The string ;' is encountered. The string {}'被在命令参数中出现的任何位置处理的当前文件名替换,而不仅仅是在某些版本的find中的参数中。 这两种结构都可能需要进行转义(使用“\\”)或引用以保护它们不被shell扩展。 有关使用-exec选项的示例,请参阅“示例”部分。 为每个匹配的文件运行一次指定的命令。 该命令在起始目录中执行。 围绕使用-exec操作存在不可避免的安全问题; 你应该使用-execdir选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM