我误读了gzip文档,现在我必须删除大量的" .gz"来自许多目录的文件。我尝试使用' find'找到所有.gz文件。但是,只要名称中有空格的文件,rm就会将其解释为另一个文件。只要有短划线,rm就会将其解释为新旗帜。我决定使用' sed'用" \"替换空格和#34; \ - "的空格划线,以及我的想法。
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,所以我不得不假设我对正则表达式做错了。如果你知道我做错了什么,或者你有更好的解决方案,请告诉我。
答案 0 :(得分:8)
在空格之前添加反斜杠可以保护空间免受shell源代码中的扩展。但是命令替换中的命令输出不进行shell解析,只进行通配符扩展和字段拆分。在空格之前添加反斜杠不会保护它们免受字段拆分。
在破折号之前添加反斜杠完全没用,因为rm
将破折号解释为特殊符号,并且它不会将反斜杠解释为特殊。
find
的输出通常不明确 - 文件名可以包含换行符,因此您不能使用换行符作为文件名分隔符。解析find
的输出通常会被破坏,除非您处理已知的受限字符集中的文件名,并且它通常不是最简单的方法。
find
具有执行外部程序的内置方式:-exec
操作。没有进行解析,因此文件名中的特殊字符不会出现任何问题。 (以-
开头的路径仍然可以解释为一个选项,但所有路径都以.
开头,因为那是遍历的目录。)
find . -type f -name '*.gz' -exec rm {} +
许多find
实现(Linux,Cygwin,BSD)可以在不调用外部实用程序的情况下删除文件:
find . -type f -name '*.gz' -delete
有关编写健壮的shell脚本的更多信息,请参阅Why does my shell script choke on whitespace or other special characters?。
答案 1 :(得分:1)
无需管道输入sed等。您可以使用-exec
上的find
标志,它允许您对每个结果执行命令。命令。
例如,对于您的情况,这将起作用:
find . -type f -name '*.gz' -exec rm {} \;
与:
大致相同find . -type f -name '*.gz' -exec rm {} +
最后一个没有打开每个结果的子shell,这使得它更快。
来自man find
:
-exec command;
执行命令;如果返回0状态,则返回true。以下全部 查找的参数被认为是命令的参数,直到 由
;' is encountered. The string
{}'组成的参数是 由当前正在处理的文件名替换 在命令的参数中,而不仅仅是在参数中 单独,如某些版本的查找。这两种结构都是如此 可能需要转义(使用“\”)或引用以保护它们 由shell扩展。有关示例,请参见“示例”部分 使用-exec选项。指定的命令运行一次 每个匹配的文件。该命令在起始目录中执行。 使用-exec时存在不可避免的安全问题 行动;你应该使用-execdir选项。