使用perl数组比较文件名以查找匹配的mp3和m4a文件类型

时间:2014-08-14 20:06:09

标签: arrays regex perl filenames

我填充了一个数组,其中包含文件扩展名为mp3的所有文件以及包含所有m4a文件的单独数组,如下所示

my @mp3filesarray = grep ( -f ,<*.mp3>);
my @m4afilesarray = grep ( -f ,<*.m4a>);

我想要做的是比较数组的文件名以查看是否存在匹配或部分匹配,如果存在,则将mp3文件和m4a文件复制到新的子目录中,以便我可以查看文件以确定我要保留哪个文件。我确信我需要使用正则表达式,但我不知道如何做到这一点。我很感激任何帮助。感谢。

3 个答案:

答案 0 :(得分:3)

以下是我如何做到这一点。

use strict;
use warnings;
use File::Path qw(make_path);
use File::Copy qw(move);

my %seen;
while ( my $file = glob '*.{mp3,m4a}' )
{
    ++$seen{ substr($file, 0, length() - 4) };
}

for my $dupe ( grep { $seen{$_} > 1 } keys %seen )
{
    make_path($dupe);
    move("$dupe.$_", "$dupe/$dupe.$_" for (qw(mp3 m4a)); # Change / to \ if you're on Windows
}

我首先将所有以m4a或mp3结尾的文件全局化,然后将其剥离为没有扩展名的基本名称并将其哈希。然后我遍历任何重复项并将它们移动到自己的文件夹中。

正则表达式会过度,因为glob扩展语法比正则表达式限制得多。

此方法仅查找重复项,但唯一的区别是文件扩展名。要进行模糊匹配,您需要的技术与我使用的O(n)散列策略不同。


第一个while循环也可以使用File::Basename::fileparse()编写,如下所示:

while (my $file = glob '*.{mp3,m4a}')
{
    my $name = fileparse($file, qr/ [.] [^.]* \z/x);
    ++$seen{$name};
}

答案 1 :(得分:0)

您要做的事情非常昂贵 - 为了寻找部分匹配,您需要将每个文件名与每个其他文件名进行比较。大概你不想将mp3列表相互比较,这使得 little 更容易。

我选择foreach循环:

my %files;

foreach my $file ( glob ( '*.mp3 *.m4a' ) {
    my ( $name, $type ) = ( $file =~ m/(\w+)\.(m[4p][a3])/ );
    $files{$type}{$name}++;
}

foreach my $mp3_file ( keys %{ $files{'mp3'} } ) {
    if ( $files{'m4a'} ) { print "Dupe detected: mp3_file\n"; next; }
    foreach my $m4a_file ( keys %{ $files{'m4a'} } ) {
        if ( $mp3_file =~ m/\Q$m4a_file/ ) { print "Partial match $mp3_file $m4a_file\n"; }
        if ( $m4a_file =~ m/\Q$mp3_file/ ) { print "Partial match $m4a_file $mp3_file\n"; }
    }
}

类似的东西 - 你正在对文件名做一个直接的子串比较 - 没有扩展名。你想用m4a到mp3比较做同样的事情。 (如果你准备将每个文件与每个文件进行比较而不依赖于扩展名,你可以简化一下,但你也增加了比较次数...当然,你保证至少有一个重复:))

答案 2 :(得分:0)

如果您的文件中没有任何数字(如1.mp3或a12b.m4a),那么这将有效:

use strict;
use warnings;

system("sudo mkdir review");

my (@spmp3,@spm4a);
my @mp3file=`ls | grep mp3`;
my @m4afile=`ls | grep m4a`;


for (my $i=0; $i<=$#mp3file; $i++)
{
  @spmp3 = split (/\./, $mp3file[$i]);
}

for (my $j=0; $j<=$#m4afile; $j++)
{
  push (@spm4a,  split (/\./, $m4afile[$j]));
}

for (my $k=0; $k<=$#mp3file; $k=$k+2)
{
  for (my $l=0; $l<=$#m4afile; $l=$l+2)
  {
    if ( $spmp3[$k] eq  $spm4a[$l] )
    {
      system(" mv $spmp3[$k].mp3 $spm4a[$k].m4a ./review");
    }
  }
}