同じ名前のファイルを見つけて、小さいサイズのコピーをすべて削除し、大きいサイズのコピーだけを残そうとしています。例:test.jpg = 2kb、test.jpg = 9kb、test.jpg=5kb。2kbと5kbのファイルは削除され、9kbだけが残ります。私はこれを行うためにいくつかのGUIプログラムを試しましたが、コピーが見つかった後にすべてを手動で削除する必要があったため、役に立ちませんでした(400000の重複がある場合はあまり良くありません!)誰もが知っているこれをしますか?
2 に答える
1
これにより、すべてのファイルが検索され、それらの名前、サイズ、パス付きの名前が出力されます。次に、名前、サイズ (降順)、パスの順に並べ替えます。スクリプトは、最初 (最大) 以外の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
于 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 に答える