我误读了 gzip 文档,现在我必须从彼此内部的许多目录中删除大量“.gz”文件。我尝试使用“查找”来定位所有 .gz 文件。但是,只要文件名中有空格,rm 就会将其解释为另一个文件。每当出现破折号时, rm 都会将其解释为一个新标志。我决定使用 'sed' 用“\”替换空格,用“\-”替换空格破折号,这就是我想出的。
find . -type f -name '*.gz' | sed -r 's/\ /\\ /g' | sed -r 's/\ -/ \\-/g'
例如,当我对名称为“Test - File - for - show.gz”的文件运行 find/sed 查询时,我得到输出
./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
行动。没有进行解析,因此这不会受到文件名中特殊字符的任何问题的影响。 (以 -
开头的路径仍然可以解释为一个选项,但所有路径都以 .
开头,因为这是要遍历的目录。)
find . -type f -name '*.gz' -exec rm {} +
许多
find
实现(Linux、Cygwin、BSD)可以在不调用外部实用程序的情况下删除文件:find . -type f -name '*.gz' -delete
见 Why does my shell script choke on whitespace or other special characters?有关编写健壮的 shell 脚本的更多信息。
关于regex - 如何递归删除某种类型的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25481250/