Удаление файлов меньшего размера из файлов - PullRequest
0 голосов
/ 30 октября 2009

Я пытаюсь найти файлы с одинаковыми именами и удалить все копии меньшего размера, оставив только самые большие. Например: test.jpg = 2 КБ, test.jpg = 9 КБ, test.jpg = 5 КБ. Файлы 2 КБ и 5 КБ будут удалены, оставив только 9 КБ. Я попробовал пару программ с графическим интерфейсом, чтобы сделать это, и они не помогли, так как вы должны были удалить все вручную после того, как он нашел копии (не очень хорошо, когда есть около 400000 дубликатов!) Есть ли сценарий, который может сделать это, что кто-нибудь знает?

Ответы [ 2 ]

1 голос
/ 30 октября 2009

Это находит все файлы и печатает их имена, размеры и имя с путем. Затем он сортирует их по имени, затем по размеру (по убыванию), затем по пути. Скрипт awk проходит через все, кроме первого (самого большого), и xargs передает их на echo (удалите echo, чтобы заставить rm действовать). Это должно работать с файлами с пробелами в их именах, но не с теми, в именах которых есть новые строки или символы табуляции.

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
0 голосов
/ 30 октября 2009

Этот скрипт perl находит все файлы, начиная с текущего каталога. Затем он помещает их в хеш, где базовое имя файла является ключом, а значение - парой (размер, полный путь). Затем он перебирает базовые имена, сортирует дубликаты и удаляет все, кроме самого большого.

Фактический / 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";
    }
}
...