【问题标题】:i want to rename more than 20k files with a script, but it fails: "argument list too long"我想用脚本重命名超过 20k 的文件,但它失败了:“参数列表太长”
【发布时间】:2017-04-21 21:49:34
【问题描述】:

我通过这个创建这些文件

for((i=0;i<20000;i++)
do
 touch "www.google.com electronic&information this is bash test ${date} .txt"
done

然后,我想将 "www.google.com" 替换为 "HNSD" 。 在 20k 个文件中,所有文件名都包含空格。


我的第一次尝试如下:

rename 's/www.google.com/HNSD/g' *

...但这会产生“参数列表太长”的错误。


我的第二次尝试如下:

 #!/bin/bash
function _rename ()
{ 
while read line1; do
#rename 's/www.google.com/HNSD/g' $line1
sed -i "s/www.google.com/HNSD/g" $line1
#echo $line1
done
}

ls -1 | _rename

...但这不会重命名给定的文件。这应该怎么做?

【问题讨论】:

  • 不要在脚本中使用ls -1。不要使用 read 前面没有 IFS= 和后面的 -r 参数。不要使用未引用的参数。并且不清楚你是如何得到这个错误的,除非你有一个更长的参数列表,而不是作为 single 行传递给命令(例如sed)的一行,因为“参数列表太长”错误基于每个单独的外部命令的 argv。
  • sed -i 根本不重命名文件;相反,它改变了它们的内容——所以不清楚你希望这个脚本如何实现你的既定目标。
  • 另外,不要使用 function 关键字——它会使您的代码与 POSIX sh 不兼容,而不会增加兼容语法的任何好处。
  • 参见ParsingLS(关于为什么永远不应以编程方式使用ls)、BashFAQ #30(关于重命名)和BashFAQ #1(关于正确使用while read)。
  • 哦,对不起。我在目录中尝试 $rename 's/www.google.com/HNSD/g' *。它提示参数列表太长。然后,我想创建一个脚本并制作一个圆圈来重命名这些文件名。

标签: linux bash shell sed rename


【解决方案1】:

对每个文件运行单个 mv 命令不会导致此问题,除非文件名本身太长(或者您的环境太满,从而挤占了与 argv 使用共享的空间)以至于无法容纳同时在命令行上同时显示源名称和目标名称。因此,以下通常是相当安全的:

for f in *www.google.com*; do
  mv "$f" "${f//www.google.com/HNSD}"
done

这里,我们使用parameter expansion 来执行重命名操作。


原始代码有问题,因为它试图将所有文件名一次性放在命令行上。如果您使用xargsfind -exec {} + 将您的操作拆分为多个调用,您将不会遇到这个问题。如果您有rename,并希望尽可能少地调用它来处理当前位置的所有目录条目,则如下所示:

printf '%s\0' * | xargs -0 rename 's/www.google.com/HNSD/'

【讨论】:

    【解决方案2】:

    两种选择:


    使用find,并在-exec 操作中使用rename(或类似名称)重命名:

    find . -type f -name '*www.google.com*' -exec rename 's/www.google.com/HNSD/g' {} +
    

    利用for 循环遍历文件:

    for f in *www.google.com*; do rename 's/www.google.com/HNSD/g' "$f"; done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多