我正在尝试查找具有相同名称的文件,并删除所有较小尺寸的副本,只留下最大的副本。例如:test.jpg = 2kb,test.jpg = 9kb,test.jpg = 5kb。 2kb和5kb文件将被删除,只留下9kb。我已经尝试了几个GUI程序来做这个并且他们没有帮助,因为你必须在找到副本后手动删除所有内容(当有大约400000个欺骗时不太好!)是否有一个可以的脚本这样做是否有人知道?
答案 0 :(得分: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”的所有文件,但{50}字节最大的test/dir/dir/file
除外。
test
|-- [ 26] file
|-- [ 4096] dir
| |-- [ 34] file
`-- [ 4096] dir
|-- [ 4096] dir
| |-- [ 50] file
`-- [ 4096] test
`-- [ 4096] dir
`-- [ 20] file
答案 1 :(得分:0)
此perl脚本查找从当前目录开始的所有文件。然后它将它们放入一个散列,其中文件的basename是键,值是(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";
}
}