use strict; use IO::File; my %du1; recursetree(\%du1, readdu(shift), ""); my %du2; recursetree(\%du2, readdu(shift), ""); my $changed= diffdu(\%du1, \%du2); # du1 now contains the entries only in du1, etc. print "only in first\n"; my $n=0; for my $d (sort {$du1{$b} <=> $du1{$a} } keys %du1) { printf("<%8d %s\n", $du1{$d}, $d); last if $n++ ==10 && $du1{$d}<10000; } print "only in second\n"; $n=0; for my $d (sort {$du2{$b} <=> $du2{$a} } keys %du2) { printf(">%8d %s\n", $du2{$d}, $d); last if $n++ ==10 && $du2{$d}<10000; } print "changes\n"; my @changeddirs= sort {$changed->{$b} <=> $changed->{$a}} keys %$changed; my $di=1 ; while ($di<=10 && $changed->{$di}<10000) { my $d= $changeddirs[$di++]; printf("%s%8d %s\n", ($changed->{$d}<0)?("-", -$changed->{$d}):("+", $changed->{$d}), $d); } my $di=-2; while ($di>=-11 && $changed->{$di}>-10000) { my $d= $changeddirs[$di--]; printf("%s%8d %s\n", ($changed->{$d}<0)?("-", -$changed->{$d}):("+", $changed->{$d}), $d); } sub readdu { my $fn=shift; my $fh= IO::File->new($fn, "r") or die "$fn: $!\n"; my $root= { subdirs=>{}, dutotal=>0, subtotal=>0, }; while (<$fh>) { if (/(\d+)\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); } $p->{dutotal}= $total; $q->{subtotal}+=$total if ($q); } } $fh->close(); return $root; } sub recursetree { my ($du, $dir, $path)= @_; $du->{$path}= ($dir->{dutotal}-$dir->{subtotal})/2; #$dir->{dutotal}/2 recursetree($du, $dir->{subdirs}{$_}, $path.'/'.$_) for keys %{$dir->{subdirs}}; } sub diffdu { my ($du1, $du2)= @_; my %changed; for my $d (keys %$du1) { if (exists $du2->{$d}) { my $diff= $du2->{$d}-$du1->{$d}; delete $du2->{$d}; delete $du1->{$d}; $changed{$d}= $diff if ($diff); } } return \%changed; }