use strict; use warnings; my $root= { subdirs=>{}, dutotal=>0, subtotal=>0, }; my %m= ( B=>1, K=>1024, M=>1024*1024, G=>1024*1024*1024, T=>1024*1024*1024*1024 ); while (<>) { if (/^\s*(\d+(?:\.\d+)?[GMKB]?)\s+(?:\/|\.\/)?(.*?)\s*$/) { my ($total, $path)= ($1, $2); my @path= split /\//, $path; my $p= $root; my $q= undef; for my $dir (@path) { if (!exists $p->{subdirs}{$dir}) { $p->{subdirs}{$dir}= { subdirs=>{}, dutotal=>0, subtotal=>0, }; } ($p,$q)= ($p->{subdirs}{$dir}, $p); } if ($total =~ /(\d+(?:\.\d+)?)([GMKB])/) { $total = $1 * ($m{$2}/512); } $p->{dutotal}= $total; $q->{subtotal}+=$total if ($q); } } printdir($root, ""); sub printdir { my ($dir, $path)= @_; printf("%10d %10d %s\n", ($dir->{dutotal}-$dir->{subtotal})/2, $dir->{dutotal}/2, $path); printdir($dir->{subdirs}{$_}, $path.'/'.$_) for keys %{$dir->{subdirs}}; }