我正在尝试查找具有相同名称的文件并删除所有较小的副本,只留下最大的副本。例如:test.jpg=2kb,test.jpg=9kb,test.jpg=5kb。2kb 和 5kb 的文件将被删除,只留下 9kb。我已经尝试了几个 GUI 程序来执行此操作,但它们没有任何帮助,因为您必须在找到副本后手动删除所有内容(当有大约 400000 个重复项时,这不是很好!)是否有脚本可以这样做有人知道吗?
问问题
92 次
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 脚本查找从当前目录开始的所有文件。然后将它们放入一个散列中,其中文件的基本名称是键,值是 (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 回答