重复文件名需要Perl脚本帮助

时间:2017-12-05 09:00:37

标签: perl

我开发了下面的shell脚本来查找文件名的重复部分并将其删除。同样我需要在Perl脚本中进行准备,因为perl脚本文本处理花费的时间较少。

#!/bin/bash
for i in `ls -t *xml|awk 'BEGIN{FS="_"}{if (++dup[$1] >= 2) print}'`;
do
rm $i
done 

我必须以这样的方式为我的perl脚本准备我的代码,例如只有最近修改过的文件名模式

File 1: AAA_555_0000 
File 2: AAAA_123_123 
File 3: AAAA_452_452 [latest]

File 4: BBB_555_0000 
File 5: BBB_555_555 
File 6: BBB_999_999 [latest]

File 7: CCC_555_0000 
File 8: CCC_000_000 
File 9: CCC_000_111 [latest]

Perl Script必须在文件夹中的所有文件名模式(文件名的一部分)中选择最新文件,它应该比较并删除重复项。 例如:脚本必须以AAA文件名模式选择最新文件,如果发现模式必须删除,则必须与其他AAA模式进行比较。最后,只保留所有文件名模式中的最新文件。

感谢你能否帮我解决这个问题。

非常感谢!

1 个答案:

答案 0 :(得分:0)

您的问题对我来说有点不清楚,因为我不确定您如何确定文件的顺序来判断哪个文件更新。此代码将执行我认为您需要的操作:

my $dir = shift || '.';

opendir(my $dh, $dir);
my @files = sort grep !/^\./, readdir($dh);

my $last;
my @batch;
foreach my $f (@files) {
  my @parts = split /_/, $f;

  if( !$last ) {
    $last = $parts[0];
    push @batch, [ @parts ];
  }
  elsif( index($last, $parts[0]) != -1 ) {
    push @batch, [ @parts ];
  }
  else {
    delete_files(@batch);

    @batch = ([ @parts ]);
    $last  = $parts[0];
  }
}
delete_files(@batch);

sub delete_files {
  my @batch = @_;

  @batch = sort {
    $a->[0] cmp $b->[0] ||
    $a->[1] cmp $b->[1] ||
    $a->[2] cmp $b->[2]
  } @batch;
  pop @batch;

  map { print "Delete: ", join('_', @$_), "\n"; } @batch;
}

它假定文件的批次是文件具有相同前缀的文件(直到第一个'_'字符)。当两个前缀具有不同的长度时,则公共长度必须匹配。

它还假设应该比较“版本号”(用'_'分隔的文本位),最左边的是最有意义的。

鉴于这些假设,代码指向包含您提及的文件的目录,输出:

# latest.pl <dir>
Delete: AAA_555_0000
Delete: AAAA_123_123
Delete: BBB_555_0000
Delete: BBB_555_555
Delete: CCC_000_000
Delete: CCC_000_111

不清楚的部分是你认为文件7不是最新的......

订单清除后,您可以更改以下行:

map { print "Delete: ", join('_', @$_), "\n"; } @batch;

使用:

map { unlink join('_', @$_); } @batch;

这样它就会删除文件。

您可以在sub中使用排序算法,这是确定要删除哪些文件的排序算法。现在它将文件名部分从左到右比较为字符串。您可以在必要时使用<=>作为数字进行比较,而不是cmp