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/