/usr/bin/rename:参数列表太长(大量重命名文件)

Posted

技术标签:

【中文标题】/usr/bin/rename:参数列表太长(大量重命名文件)【英文标题】:/usr/bin/rename: Argument list too long (mass renaming files) 【发布时间】:2017-06-18 21:09:36 【问题描述】:

我正在尝试通过截断文件名中第一个空格出现的文件来批量重命名某些文件。我编写了一个简单的脚本来重命名:

for i in *.fa; do rename 's/\s.*//' *.fa; done

这在测试中工作得很好,并根据需要产生以下结果:

$:~/testenv$ ls
NM_000016.5_LastMex1_4_12 23 0 1 KB882088_3062975-30.fa  NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa
$:~/testenv$ for i in *.fa; do rename 's/\s.*//' *.fa; done
$:~/testenv$ ls
NM_000016.5_LastMex1_4_12  NM_000016.5_PastMex1_4_12

不幸的是,我必须对很多文件执行此操作,大约 670 万个。这给了我以下错误:

/usr/bin/rename: Argument list too long

我已经尝试了所有我能想到的技巧,即使我使用 find 它似乎也无法获取文件。

$:~/testenv$ ls
NM_000016.5_astMex1_4_12 23 0 1 KB882088_3062975-30.fa   NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa
NM_000016.5_LastMex1_4_12 23 0 1 KB882088_3062975-30.fa    
$:~/testenv$ find . -maxdepth 1 -type f -exec sh -c 'rename 's/\s.*//' *.fa' _  \;
find: `./NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa': No such file or directory
find: `./NM_000016.5_astMex1_4_12 23 0 1 KB882088_3062975-30.fa': No such file or directory

任何帮助将不胜感激。

【问题讨论】:

for i in *.fa; do rename 's/\s.*//' *.fa; done,当它工作时,重命名所有 .fa 文件每个文件一次,这意味着,如果你有 1000 个文件,你将重命名所有 1000 个文件 1000次,总计 1,000,000 次潜在操作。这肯定不是你想要的。 那些ls 示例如果替换为ls -1Q 示例会更容易阅读。 (-1Q 每行列出一项,引用。) @agc, ...虽然是非 POSIX 扩展,但不能保证 OP(或其他任何人)可以使用它。 【参考方案1】:

你有这个错误是因为你使用 *.fa 不仅作为 glob 进行迭代,而且还将它扩展到单个 rename 命令的命令行,其中名称列表超出了操作系统的最大参数向量长度。您不会遇到以下问题:

# run rename once per *.fa file, with only one name given each run
for i in *.fa; do rename 's/\s.*//' "$i"; done

...或其更高效的表亲:

# only tries to rename files that actually have a space in their name
# runs "rename" only as many times as necessary -- not once per file, like the above.
find . -name '*[[:space:]]*.fa' -exec rename 's/\s.*//'  +

也就是说,这个用例根本不需要外部rename 命令。

# Rename all files with a space in their name, then ending in .fa, to truncate at the space
for i in *[[:space:]]*.fa; do
  mv -- "$i" "$i%%[[:space:]]*"
done

如果您想保留扩展名,则可能是:

for i in *[[:space:]]*.fa; do
  mv -- "$i" "$i%%[[:space:]]*.fa"
done

【讨论】:

您确定不想执行mv 670 万次吗?这不是坚持find -exec rename + 的好理由吗? @MarkSetchell,啊,但是真的有 670 万个文件需要重命名吗?我在这里猜测我们将很多名称传递给rename,这些名称已经很好了——因此改进了 glob 以仅查找其中包含空格的名称。 @charles-duffy 嘿,谢谢,您的解决方案运行良好。但是发生的一件事是我在少数文件的中间遇到了no space left on device 错误。这很奇怪,因为我有很多空间。有任何想法吗? /dev/dm-0 17T 252G 16T 2% / @charles-duff 是的,所有 670 万个文件都需要重命名。它们都有空格。 @bhffs,我建议查看您的空闲 inode,而不是仅查看空闲块。

以上是关于/usr/bin/rename:参数列表太长(大量重命名文件)的主要内容,如果未能解决你的问题,请参考以下文章

参数列表太长:递归头扩展失败

为啥在传递引用的参数时会得到“/bin/sh:参数列表太长”?

Unix tar返回参数列表太长[重复]

“参数列表太长”限制是不是适用于 shell 内置函数?

text 删除文件参数列表太长

sh 删除不带参数列表的时间太长