xargs 与 rm + 文件名包含空格

Lov*_*ths 3 linux shell find xargs

我正在编写一个简单的程序来删除所有获取的文件。文件可以包含空格,所以我添加了引号,如下所示

find -name "*.scala" | xargs -d "\n" -I {} rm \"{}\"
Run Code Online (Sandbox Code Playgroud)

以上失败并出现错误:无法删除,没有这样的文件或目录。但是如果我列出相同的文件,它们就在那里。此外,如果我在下面执行并使用 bash 执行它;有用

find -name "*.scala" | xargs -d "\n" -I {} echo rm \"{}\" | bash
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么第一种情况不起作用吗?

Kus*_*nda 6

xargs -d "\n" -I {} rm \"{}\"
Run Code Online (Sandbox Code Playgroud)

这假设 GNU coreutils 的版本xargs支持-d指定分隔符的选项。

这不会与您的find命令一起使用,因为它会向由find. 这意味着,不是 ,而是使用文字路径名./somedir/file.scala调用。rm"./somedir/file.scala"

例子:

$ touch hello
$ touch '"hello"'
$ ls
"hello" hello
$ echo hello | xargs -d "\n" -I {} rm \"{}\"
$ ls
hello
Run Code Online (Sandbox Code Playgroud)

当您将生成的命令通过管道传输到时,它会起作用,bash因为bash会删除引号。

如果您一开始就没有付出额外的努力来添加引号,它也可能会起作用:

xargs -d "\n" -I {} rm {}
Run Code Online (Sandbox Code Playgroud)

要正确删除文件,请使用

find . -type f -name '*.scala' -delete
Run Code Online (Sandbox Code Playgroud)

或者,如果您仍想使用xargs

find . -type f -name '*.scala' -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)

它将find和之间的路径名xargs作为空分隔列表传递。Nul ( \0) 是唯一不允许出现在 Unix 系统路径名中的字符。文件名也可以不包含/,但允许换行。

第三种选择是rm直接从调用find

find . -type f -name '*.scala' -exec rm {} +
Run Code Online (Sandbox Code Playgroud)

请注意,{}不需要(也不应该)引用它,因为它find非常清楚如何将带有空格(或换行符或其他任何内容)的路径名传递给命名实用程序。