0

我正在尝试查找具有相同名称的文件并删除所有较小的副本,只留下最大的副本。例如:test.jpg=2kb,test.jpg=9kb,test.jpg=5kb。2kb 和 5kb 的文件将被删除,只留下 9kb。我已经尝试了几个 GUI 程序来执行此操作,但它们没有任何帮助,因为您必须在找到副本后手动删除所有内容(当有大约 400000 个重复项时,这不是很好!)是否有脚本可以这样做有人知道吗?

4

2 回答 2

1

这会找到所有文件并打印它们的名称、大小和名称与路径。然后它按名称对它们进行排序,然后按大小(降序)然后按路径排序。该awk脚本通过除第一个(最大)之外的所有脚本并将xargs它们交给echo(删除echorm采取行动)。这应该适用于名称中包含空格的文件,但不适用于名称中包含换行符或制表符的文件。

find -type f -printf "%f\t%s\t%p\n" |
    sort -t $'\t' -k 1,1 -k 2,2rn -k 3,3 |
    awk -F'\t' '{if ( $1 == prevfile) printf "%s\0", $3; prevfile = $1}' |
    xargs -0 -I{} echo rm \{\}

在这个目录结构(由 产生tree -s)中,所有名为“file”的文件都将被删除,除了test/dir/dir/file最大的文件为 50 字节。

test
|-- [    26]  file
|-- [  4096]  dir
|   |-- [    34]  file
`-- [  4096]  dir
    |-- [  4096]  dir
    |   |-- [    50]  file
    `-- [  4096]  test
        `-- [  4096]  dir
            `-- [    20]  file
于 2009-10-30T05:47:38.063 回答
0

这个 perl 脚本查找从当前目录开始的所有文件。然后将它们放入一个散列中,其中文件的基本名称是键,值是 (size, fullpath) 对。然后它遍历基本名称,对重复项进行排序并删除除最大的之外的所有名称。

实际的 /bin/rm 被注释掉了。在真正做之前,请确保它符合您的要求。

真正的 perl 黑客:如果我在这里做一些幼稚/愚蠢的事情,我很想了解这一点。

#!/usr/bin/perl -w
use File::Basename;
use strict;

my @files = `/usr/bin/find -type f`;
my %stats;

# each hash key is the simple basename of the files
# each hash value is a 2 element array of (size, fullpath)
foreach my $file (@files)
{
    chomp($file);
    my $result = `/bin/ls -s $file`;
    chomp($result);
    if($result =~ /^(\d+)\s+(.*)/)
    {   
        my ($basefile, $dir, $suffix) = fileparse($file);
        push(@{$stats{$basefile}}, [$1, $2]);
    }
    else
    {   
        printf STDERR "Unexpected ls output: $result\n";
    }
}

foreach my $file (keys %stats)
{
    # sort from smallest to largest
    my @sorted = sort {$b->[0] <=> $a->[0]} @{$stats{$file}};

    # remove the biggest one
    pop(@sorted);

    # for each one that's left remove it (use at your own risk!)
    foreach my $path (@sorted)
    {   
        # system("/bin/rm $path");
        printf "/bin/rm $path->[1]\n";
    }
}
于 2009-10-30T02:00:17.413 回答