一次从多个文件中删除公共前缀

Remove a common prefix from many files at once

我必须对单个文件夹中的多个文件执行以下操作:

Remove "Sword of the Stranger - " part from the file names like "Sword of the Stranger - Aganai No Yuki - ストレンヂア無皇刃譚 - [20-25].mp3".

为此,我构建了以下命令:

find . -name '*.mp3' -exec sh -c "cp {} `echo {} | cut -f2- -d'-' | cut -c2-`" \;

但是在执行上述命令时出现以下错误:

cp: target ‘}’ is not a directory

即使我更改上述命令以考虑文件名中的空格,它仍然会给我同样的错误。

find . -name '*.mp3' -exec sh -c "cp {} "`echo {} | cut -f2- -d'-' | cut -c2-`"" \;

请有人解释为什么我收到错误并建议使用另一个 liner 来执行上述操作(最好使用 find 和 exec 和 cp)。

问题是double-quotes不阻止命令替换;也就是说,像这样:

echo "`echo foo`"

打印 foo 而不是 `echo foo`.

因此在您的示例中,命令替换发生在之前 find 被调用。也就是这个:

find . -name '*.mp3' -exec sh -c "cp {} `echo {} | cut -f2- -d'-' | cut -c2-`" \;

相当于:

find . -name '*.mp3' -exec sh -c "cp {} }" \;

因为命令 echo {} | cut -f2- -d'-' | cut -c2- 打印 }.

要解决此问题,您可以改用 single-quotes。

此外,您需要在命令的几个地方使用 double-quotes,以防止您的文件名被解释为 echocp 的多个参数:

find . -name '*.mp3' -exec sh -c 'cp "{}" "`echo "{}" | cut -f2- -d- | cut -c2-`"' \;

(请注意,我还将 -d'-' 更改为 -d-。无论如何,它们是等价的,因此无需做任何花哨的事情即可将 -d'-' 放入 single-quoted 字符串。)