批量重命名驼峰文件以包含空格

批量重命名驼峰文件以包含空格

我正在尝试批量重命名以驼峰命名的文件,以包含相邻大小写字母之间的空格。我使用的是 Mac 操作系统,因此我使用的实用程序是 BSD 变体。

例如:

250 - ErosPhiliaAgape.mp3 => 250 - Eros Philia Agape.mp3

我正在尝试使用以下命令将find相关文件通过管道传输到在子 shell 中mv运行的文件:sed

find . -name "*[a-z][A-Z]*" -print0 | xargs -0 -I {} mv {} "$(sed -E 's/([a-z])([A-Z])/\1 \2/g')"

单独来看,这些命令工作得很好:find提取正确的文件并sed正确重命名它,但是当我将它们与 xargs 结合使用时,什么也没有发生。

我需要改变什么才能使这项工作正常进行?

答案1

问题是$(...)命令中的子 shell 是在运行命令时评估的,而不是xargs针对每个文件评估的。您可以使用find's-exec来计算 a 中每个文件的命令sh,并适当地替换引用:

find . -name "*[a-z][A-Z]*" -type f -exec sh -c 'echo mv -v "{}" "$(echo "{}" | sed -E "s/([a-z])([A-Z])/\1 \2/g")"' \;

如果这个输出看起来不错,请删除echoin echo mv。请注意,由于echo | sed,这不适用于嵌入\n. (但这是您自己的尝试中已经存在的限制,所以我希望这是可以接受的。)

答案2

您的sed命令正在从管道获取输入。它与 竞争xargs,因此两个命令中的每一个都会获取由 写入的部分数据find(每个字节仅发送到一个读取器),并且无法预测哪个命令接收什么。

您需要将每个文件名通过管道传输到 中sed,这意味着您需要一个中间 shell 来设置管道。

find . -name "*[a-z][A-Z]*" -print0 | xargs -0 -I {} sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {}

你不需要xargs,它基本上没有用。find可以直接调用程序。

find . -name "*[a-z][A-Z]*" -exec sh -c 'mv "$0" "$(echo "$0" | sed -E '\''s/([a-z])([A-Z])/\1 \2/g'\'')"' {} \;

或者,安装任何 Perlrename实现,例如File::Rename或来自Unicode::Tussle

cpan File::Rename
find -depth . -exec rename 's!([a-z])([A-Z])(?!.*/)!$1 $2!g' {} +

(?!.*/)位可防止在目录名称中触发替换(如果目录名称包含驼峰命名法)。传递-depthfind可确保如果重命名目录,则在find遍历该目录后会发生这种情况。

答案3

如果您更喜欢使用 GNU Parallel,解决方案是:

find . -name "*[a-z][A-Z]*" -type f | parallel mv -v {} '{= s:([a-z])([A-Z])(?!.*/):$1 $2:g =}'

相关内容