On Sat, Jan 18, 2003 at 02:02:41AM +0000, Shevek wrote:
> What is the simplest logic which will construct a tree such as that
> below. You may use any data representation you like for anything. I happen 
> to be using an SQL database which I read into a hash of (id => array of 
> children), but this isn't important.

Here's one I prepared earlier. It's recursive. It doesn't print pretty
lines, just totals directory sizes to find bloaty areas. Maybe you want
pretty lines? There was a thread on FWP recently about this if you care
to look back.

#!/usr/bin/perl -wl 
use strict;

use File::Find;
use Data::Dumper;

my $SIZE = '/:SIZE:/';
my %fs = ();
my $dir_sep = '/';

my $dir = shift || '.';
my $min_size = shift || 0;

sub wanted {
   warn("Dead link $File::Find::name\n"), return if -l && !-e;

   my @parts = split $dir_sep, $File::Find::name;
   my $size = -d $_ ? 0 : -s;   # we're chdir'ed here
   my $fs = \%fs;

   foreach my $part (@parts) {
    local $_;
    for ($fs->{$part}) {
        ($_ = {})->{$SIZE} = 0 unless defined;
        $fs = $_;
        $fs->{$SIZE} += $size;
    }
   }
}

sub lstree {
   my ($fs, $indent) = @_; $indent = 0 unless defined $indent;

   foreach my $name (
    sort {$fs->{$b}->{$SIZE} <=> $fs->{$a}->{$SIZE}}
    grep {$fs->{$_}->{$SIZE} >= $min_size}
    grep {$_ ne $SIZE} keys %$fs)
   {
    for my $entry ($fs->{$name}) {
        print "\t"x$indent, "$name\t($entry->{$SIZE})";
        lstree($entry, $indent+1) if keys %$entry > 1;
    }
   }
}

finddepth(\&wanted, $dir);
$min_size = (values %fs)[0]->{$SIZE} * $1/100 if $min_size =~ /([\d.]+)%/;
lstree \%fs;

HTH,
Paul

-- 
Paul Makepeace ....................................... http://paulm.com/

"If I am in love, then a huge swirling vortex of fluff will engulf us."
   -- http://paulm.com/toys/surrealism/

Reply via email to