in reply to Sorting based on filesize.

Someone correct me if I'm wrong, but won't sort { -s $a <=> -s $b } @files; stat each file multiple times, depending on the size and order in the array?

If so, and if RAM is cheaper than stat calls, then

@files = grep { -f } glob '* .*'; @hash{ (map { -s $_ } @files) } = @files; @files = @hash{ sort { $a <=> $b } keys %hash }; print map {$_,$/} @files;
a hash of filenames keyed on sizes could be used instead.

Replies are listed 'Best First'.
Re^2: Sorting based on filesize.
by graff (Chancellor) on Jul 20, 2004 at 04:40 UTC
    a hash of filenames keyed on sizes could be used instead.

    Well, when two or more files happen to have the same size, the hash will only keep one file name from that set. If that's okay, then yes, a simple hash like this could be used.

    If that's not okay, then you'd need a hash of arrays:

    my %hash; opendir( D, "." ); while ( $_ = readdir D ) { next unless (-f); push @{$hash{-s _}}, $_; # uses previous stat data (from -f) } for my $size ( sort {$a<=>$b} keys %hash ) { for my $file ( sort @{$hash{$size}} ) { print "$size\t$file\n"; } }
    update: added comment about how many times stat is actually called on each file (i.e. just once, not twice), and wanted to point out that the Schwartzian Transform as demonstrated by pbeckingham is likely to be the best solution overall.
      Good point. This fixes it:

      @files = grep { -f } glob '* .*'; @hash{ (map { (-s $_) . ".$_"} @files) } = @files; @files = @hash{ sort { $a <=> $b } keys %hash }; print map {$_,$/} @files;
      but it's rather a moot point - the Schwartzian Transform goes a step further and eliminates the hash.