删除较小尺寸的文件

时间:2009-10-30 01:26:10

标签: shell filenames delete-file

我正在尝试查找具有相同名称的文件,并删除所有较小尺寸的副本,只留下最大的副本。例如:test.jpg = 2kb,test.jpg = 9kb,test.jpg = 5kb。 2kb和5kb文件将被删除,只留下9kb。我已经尝试了几个GUI程序来做这个并且他们没有帮助,因为你必须在找到副本后手动删除所有内容(当有大约400000个欺骗时不太好!)是否有一个可以的脚本这样做是否有人知道?

2 个答案:

答案 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";
    }
}