【问题标题】:How can I easily bulk rename files with Perl?如何使用 Perl 轻松批量重命名文件?
【发布时间】:2010-12-22 15:14:39
【问题描述】:

我有很多要重命名的文件,我尝试创建一个正则表达式来匹配它们,但即使我被困在文件上,这些文件的命名方式如下:

文件名 01

文件名 100

文件名 02

文件名 03

等,我想在任何小于 100 的文件后面添加一个“0”(零),如下所示:

文件名 001

文件名 100

文件名 002

文件名 003

我最接近匹配它们的是使用这个 find -type d |排序-r | grep ' [1-9][0-9]$' 但是我不知道如何替换它们。提前感谢您提供的任何帮助。我在 CentOS 上,如果有帮助的话,所有这些都是通过 SSH 完成的。

【问题讨论】:

  • 你的文件名是否真的包含空格?
  • 是的,它们看起来像:“文件名 01”“文件名 101”
  • 您能详细说明机器上可用的“工具”吗?你有 perl、python、ruby 或类似的安装吗?
  • 您能否澄清您要匹配的文件的名称是哪些,以及您要避免匹配的文件名称是哪些?我在这里有点困惑。
  • Perl (5.8.8) 在机器上,但是 python 和 ruby​​ 没有,我很熟悉可以通过 yum 并在必要时安装它们。

标签: perl file rename bulk


【解决方案1】:

如果你的遥控器有 bash shell

for i in File*; 
do 
    case "${i##* }" in  [0-9][0-9] ) 
      echo  mv "$i" "${i% *} $(printf "%03d" ${i##* })" ;; 
    esac; 
done

删除“echo”以进行实际重命名

【讨论】:

    【解决方案2】:
    use strict;
    use File::Copy;
    
    my @files = glob 'File*Name*';
    
    foreach my $filename (@files) {
        if ($filename =~ m`^.*File.*Name.*?(\d+)`) {
            my $number = $1;
            next if ($number > 99);
            rename $filename, sprintf("FileName%03d",$number);
        }
    }
    

    【讨论】:

    • File Name 100 重命名为File Name 0100,这是无意的。
    • 你肯定是对的。添加了一些代码以使其不会发生。
    【解决方案3】:

    在我的 debian 中,它适用于重命名,用 300 个文件进行了测试。

     perl -e 'map `touch door$_.txt`, 1..300;'
     rename 's/(\d+)\.txt/sprintf("%03d.txt", $1)/e' *.txt
    

    【讨论】:

      【解决方案4】:
      perl -e 'foreach $f (glob("File\\ Name*")) { $nf = $f; $nf =~ s/(\d+)$/sprintf("%03d",$1)/e; print `mv \"$f\" \"$nf\"`;}'
      

      也许有点矫枉过正,但它确实做到了。

      【讨论】:

        【解决方案5】:

        这是一次性的吗?如果是这样,我将在这里提出一些可能被许多程序员认为是逃避现实的建议:

        将命令的输出 (find -type d | sort -r | grep ' [1-9][0-9]$') 传送到文件中,并使用编辑器以及一些全局搜索/替换魔法来创建执行重命名的脚本。

        然后扔掉脚本。

        您几乎不会大惊小怪,而且您最终会因尝试巧妙(但调试不充分)的单行线进入文件杂草而自取其辱。

        【讨论】:

        • ++!有时,使用你理解的组合比学习“深奥魔法”更好。
        • +1 我认为这类事情通常是一次性需求最实用的解决方案
        • 这可能是一种逃避,但它是一种安全的逃避......荣誉。
        • vim 中可能的全局搜索和替换魔法是:s/^\(.*\)\(\d\d\)$/mv \1 \10\2/
        • 在 Emacs 中,您可以打开目录列表,按 Cx Cq,编辑缓冲区中的文件名(例如,使用搜索和替换,或任何其他命令),保存后 Emacs 将重命名文件。
        【解决方案6】:

        你可以使用 perl 或 ruby​​ 来做一些事情。

        把所有这些文件放在同一个目录中

        dirlisting = DIR.entries('.')
        
        dirListing.each do |file| 
         num = file.match(/\d+$/).to_i
         if num < 100
           find the position where start the number, with index and inject the 0 there.
         end
        end
        

        【讨论】:

        • 你可能应该提到这段代码是 ruby​​ 而不是 perl
        • 这就是为什么我说你应该消除代码是红宝石的事实。
        【解决方案7】:

        按以下顺序运行两个命令:

        $ rename 's/File Name (\d)$/File Name 0$1/' *
        $ rename 's/File Name (\d\d)$/File Name 0$1/' *
        

        第一个重命名小于 10 的所有内容并在前面添加一个零。第二个重命名小于 100 的所有内容并在前面添加一个零。结果应该是所有文件名的三位数字。

        【讨论】:

        • rename 是标准 perl 发行版附带的实用程序。我在 Linux Bash 下运行这些。
        【解决方案8】:
        find . -type d -print0 | xargs -0 rename 's/(\d+)/sprintf "%03d", $1/e' 
        

        或类似的东西,提供

        1. 您有 GNU find 和 GNU xargs(用于 -print0-0
        2. 您拥有 perl 附带的“重命名”实用程序
        3. 文件名中只有一组数字。如果不止一个,那么您需要对正则表达式执行一些操作,使其仅匹配您要重新格式化的数字。

        【讨论】:

        • 这与我的建议很接近,使用 sed 而不是 xargs,所以我会 +1。
        • 我知道 xargs 是要走的路,但我无法编写确切的命令。
        • +1 用于列出依赖项(您所指的重命名实用程序可能是 yum 或 apt-get away)。
        • 我一直很生气 cygwin perl 发行版不包含重命名。
        【解决方案9】:

        我认为mmv 是你这里的朋友。

        【讨论】:

          猜你喜欢
          • 2014-10-31
          • 1970-01-01
          • 2012-12-24
          • 2010-11-19
          • 2010-10-17
          • 1970-01-01
          • 2014-12-20
          • 2017-12-13
          • 1970-01-01
          相关资源
          最近更新 更多