如何筛选文件列表以删除已知重复项



我有以下文件列表: INV_1400524_20170412_052945.pdf INV_1400524_20170412_063522.pdf INV_1400524_20170412_090338.pdf INV_1400524_20170412_092911.pdf INV_1400971_20170502_095250.pdf INV_1401580_20170703_100410.pdf INV_1401880_20170804_112917.pdf RIN_1300355_20170503_014347.pdf RIN_1300552_20170518_111143.pdf RIN_1300552_20170518_122055.pdf RIN_1300688_20170627_040340.pdf RIN_1300834_20170727_113641.pdf RIN_1300834_20170727_154404.pdf

其格式为:

<Document Type>_<Document Number>_<Date>_<Time>.pdf

如您所见,由于某种原因,已多次输出相同的文档编号。我想忽略重复项并将列表过滤为唯一的文档编号和最新日期。这些文档还具有修改后的文件时间戳,如果有帮助,该时间戳与文件名中的日期和时间非常匹配。

使用 perl(我一直在使用 File::Find::Rule(,我想将列表缩减为: INV_1400524_20170412_092911.pdf INV_1400971_20170502_095250.pdf INV_1401580_20170703_100410.pdf INV_1401880_20170804_112917.pdf RIN_1300355_20170503_014347.pdf RIN_1300552_20170518_122055.pdf RIN_1300688_20170627_040340.pdf RIN_1300834_20170727_154404.pdf

我从

my @pdf_files = File::Find::Rule->new
->in($root_dir)
->name( '*.pdf' )
->mtime (">$days_ago");

但看看这个答案: 如何使用 Perl 在目录及其所有子目录中找到最新的.pl文件?

我认为也许有一种方法可以使用:

my $rule = File::Find::Rule->new;
$rule->or( $rule->new->name('INV_*.pdf')->....
$rule->or( $rule->new->name('RIN_*.pdf')->....
my @files = $rule->in($root_dir);

以对它们进行分组和过滤。有什么想法吗?

有一个很好的成语使用grep

my %seen; 
my @files = grep { not $seen{$_}++ } @files;

因为您发布增量,所以测试第一次为真,其他所有测试为假。您还可以使用正则表达式对文档 ID 进行子字符串匹配:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
chomp(
my @files = <DATA>
);
my %seen;
@files = grep { m/(d+)/ and not $seen{$1}++ } @files;
print Dumper @files;
__DATA__
INV_1400524_20170412_052945.pdf
INV_1400524_20170412_063522.pdf
INV_1400524_20170412_090338.pdf
INV_1400524_20170412_092911.pdf
INV_1400971_20170502_095250.pdf
INV_1401580_20170703_100410.pdf
INV_1401880_20170804_112917.pdf
RIN_1300355_20170503_014347.pdf
RIN_1300552_20170518_111143.pdf
RIN_1300552_20170518_122055.pdf
RIN_1300688_20170627_040340.pdf
RIN_1300834_20170727_113641.pdf
RIN_1300834_20170727_154404.pdf

这输出:

$VAR1 = [
'INV_1400524_20170412_052945.pdf',
'INV_1400971_20170502_095250.pdf',
'INV_1401580_20170703_100410.pdf',
'INV_1401880_20170804_112917.pdf',
'RIN_1300355_20170503_014347.pdf',
'RIN_1300552_20170518_111143.pdf',
'RIN_1300688_20170627_040340.pdf',
'RIN_1300834_20170727_113641.pdf'
];

如果您的条件更符合要求,则可能需要应用排序以确保将"第一个"过滤到顶部。

有两种方法 - 您可以sort文件名 - 并且因为您有一个 ISO 日期,看起来会起作用:

@files = grep { m/(d+)/ and not $seen{$1}++ } sort @files;

或者你可以根据进行stat系统调用来做一些排序(为此你需要完整的文件路径,所以要注意!

@files = grep { m/(d+)/ and not $seen{$1}++} sort { -M $a <=> -M $b } @files;

-M是检查文件年龄(以天为单位(的perl文件测试。

不过,您可以使用stat

最新更新