【问题标题】:regex for renaming files用于重命名文件的正则表达式
【发布时间】:2017-10-23 14:17:18
【问题描述】:

给定一个这样命名的文件:

2016_31_3_03_01c_02
2016_31_3_04_01a_02
2016_31_3_05_01d_02

我想批量重命名它们,使它们看起来像

2016_31_3_3_1c_02
2016_31_3_4_1a_02
2016_31_3_5_1d_02

我可以为每个文件执行rename 's/03_01c/3_1c/',但这会破坏批处理的目的。

如何为rename 命令编写正则表达式来完成此操作? 类似于:rename 's/0{0..9}_01{a..d}/,但我不知道如何编写替换部分而不替换下划线后的前导零,我想保留它。

我也不太了解删除前导零的正则表达式,但保持前导零后面的数字相同。我知道正则表达式可以找到这些实例但不替换它们。

【问题讨论】:

  • for each file 看起来像for。看看for /?
  • 是的,我将使用 for 循环,但我不明白 rename 命令所需的正则表达式。
  • 你试过rename 's/03_01c/3_1c/' *吗?
  • 这与Windows无关batch-files!

标签: regex bash rename


【解决方案1】:

只要你使用Linux,所有文件都在当前工作目录下,文件名的所有字段都是十进制的,除了第五个是十六进制,你可以这样使用

要真正重命名文件,删除@ARGV = qw/ ... / 并取消注释rename,然后调用类似的程序

perl rename.pl *

重命名.pl

use strict;
use warnings 'all';
use feature 'say';
use autodie;

@ARGV = qw/
    2016_31_3_03_01c_02
    2016_31_3_04_01a_02
    2016_31_3_05_01d_02
/;

for ( @ARGV ) {

    my @f = split /_/;
    $_ = hex for $f[4];

    my $new = sprintf('%d_%d_%d_%d_%x_%02d', @f);

    say "$_ => $new";

    # rename $_, $new;
}

输出

2016_31_3_03_01c_02 => 2016_31_3_3_1c_02
2016_31_3_04_01a_02 => 2016_31_3_4_1a_02
2016_31_3_05_01d_02 => 2016_31_3_5_1d_02

【讨论】:

    【解决方案2】:

    你可以使用下面的正则表达式

    ~s/\d{4}_\d{2}_\d{1,2}_\K0(\d)_0(\d)/$1_$2/
    

    或者你也可以试试下面的正则表达式

    ~s/0(\d)_0(\d\w+)(?=.)/$1_$2/
    

    一个班轮应该是

    perl -e ' while(glob("*")){(my $newfilename=$_)=~s/0(\d)_0(\d\w+)(?=.)/$1_$2/; rename $_, $newfilename;} '
    

    如果你在 linux 中,你可以尝试使用 ls 命令(确保你在当前目录中)

    ls | perl -ple '(my $newfilename=$_)=~s/0(\d)_0(\d\w+)(?=.)/$1_$2/; rename $_,$newfilename'
    

    【讨论】:

      猜你喜欢
      • 2011-09-14
      • 1970-01-01
      • 2017-08-10
      • 1970-01-01
      • 2013-08-06
      • 2016-08-22
      • 2020-08-13
      • 1970-01-01
      相关资源
      最近更新 更多