我开发了下面的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模式进行比较。最后,只保留所有文件名模式中的最新文件。
感谢你能否帮我解决这个问题。
非常感谢!
答案 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
。