0

同じ名前のファイルを見つけて、小さいサイズのコピーをすべて削除し、大きいサイズのコピーだけを残そうとしています。例:test.jpg = 2kb、test.jpg = 9kb、test.jpg=5kb。2kbと5kbのファイルは削除され、9kbだけが残ります。私はこれを行うためにいくつかのGUIプログラムを試しましたが、コピーが見つかった後にすべてを手動で削除する必要があったため、役に立ちませんでした(400000の重複がある場合はあまり良くありません!)誰もが知っているこれをしますか?

4

2 に答える 2

1

これにより、すべてのファイルが検索され、それらの名前、サイズ、パス付きの名前が出力されます。次に、名前、サイズ (降順)、パスの順に並べ替えます。スクリプトは、最初 (最大) 以外のawkすべてを通過し、それらを (アクションを実行するために削除) にxargs渡します。これは、名前にスペースが含まれるファイルでは機能しますが、名前に改行やタブが含まれるファイルでは機能しません。echoechorm

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 スクリプトは、現在のディレクトリから始まるすべてのファイルを検索します。次に、ファイルのベース名がキーで、値が (サイズ、フルパス) のペアであるハッシュにそれらを入れます。次に、ベース名を反復処理し、重複をソートして、最大のものを除くすべてを削除します。

実際の /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 に答える