如何比较bash shell中多个txt文件的内容并删除重复的一个(文件)

时间:2014-08-26 21:42:52

标签: bash perl shell

我试图实现这一点是Mac OS,试图通过使用fdupes实现类似但不起作用。这是我想要实现的目标:

  • 目录中有100个文件' alpha'
  • 选择一个文件A并将其与目录中的每个剩余文件进行比较' alpha'
  • 如果文件A的内容与任何文件匹配(重复),请删除重复文件
  • 移至文件B,并与剩余文件进行比较,并执行相同操作(检查重复)
  • 重复相同操作,直到检查所有文件是否有重复项。剩余文件应该是唯一的

更新

我修改了一些与此处相似的东西,但我必须多次运行才能取出重复项。它不会在单次运行中检测重复项(必须多次运行才能检测到重复项)。不确定它是否正常工作

use Digest::MD5;
%check = ();
while (<*>) {
    -d and next;
    $fname = "$_";
    print "checking .. $fname\n";
    $md5 = getmd5($fname) . "\n";
    if ( !defined( $check{$md5} ) ) {
        $check{$md5} = "$fname";
    }
    else {
        print "Found duplicate files: $fname and $check{$md5}\n";
        print "Deleting duplicate $check{$md5}\n";
        unlink $check{$md5};
    }
}

sub getmd5 {
    my $file = "$_";
    open( FH, "<", $file ) or die "Cannot open file: $!\n";
    binmode(FH);
    my $md5 = Digest::MD5->new;
    $md5->addfile(FH);
    close(FH);
    return $md5->hexdigest;
}

2 个答案:

答案 0 :(得分:1)

您应该限制必须阅读每个文件的内容的次数:

  1. 使用Path::Class或类似方法清点文件。

    一个。构建与文件大小相关的哈希值和MD5::Digest到文件名列表。

  2. 仅比较可能的重复项。匹配文件大小和摘要。

  3. 以下是未经测试的:

    use strict;
    use warnings;
    
    use Path::Class;
    use Digest::MD5;
    
    my $dir = dir('.');
    
    my %files_per_digest;
    
    # Inventory Directory
    while ( my $file = $dir->next ) {
        my $size   = $file->stat->size;
        my $digest = do {
            my $md5 = Digest::MD5->new;
            $md5->addfile( $file->openr );
            $md5->hexdigest;
        };
        push @{ $files_per_digest{"$size - $digest"} }, $file;
    }
    
    # Compare likely duplicates only
    for my $files ( grep { @$_ > 1 } values %files_per_digest ) {
        # Sort by alpha
        @$files = sort @$files;
        print "Comparing: @files\n";
    
        for my $i ( reverse 0 .. $#files ) {
            for my $j ( 0 .. $i - 1 ) {
                my $fh1 = $files->[$i]->openr;
                my $fh2 = $files->[$j]->openr;
    
                my $diff = 0;
                while ( !eof($fh1) && !eof($fh2) ) {
                    $diff = 1, last if scalar(<$fh1>) ne scalar(<$fh2>);
                }
    
                if ( $diff or !eof($fh1) or !eof($fh2) ) {
                    print "   $files->[$i] ($i) is duplicate of $files->[$j] ($j)\n";
                    $files->[$i]->remove();
                    splice @$files, $i, 1;
                }
            }
        }
    }
    

答案 1 :(得分:0)

我过去使用过rdfi​​nd非常成功。它非常准确,快速,似乎比fdupes更精简。根据{{​​3}}(RDFind's web site),可以使用MacPorts进行安装。