#----------------------------- #% du pcb #19 pcb/fix # #20 pcb/rev/maybe/yes # #10 pcb/rev/maybe/not # #705 pcb/rev/maybe # #54 pcb/rev/web # #1371 pcb/rev # #3 pcb/pending/mine # #1016 pcb/pending # #2412 pcb #----------------------------- #2412 pcb # # #| # 1371 rev # # #| | # 705 maybe # # #| | | # 675 . # # #| | | # 20 yes # # #| | | # 10 not # # #| | # 612 . # # #| | # 54 web # # #| # 1016 pending # # #| | # 1013 . # # #| | # 3 mine # # #| # 19 fix # # #| # 6 . #----------------------------- #% dutree #% dutree /usr #% dutree -a #% dutree -a /bin #----------------------------- # download the following standalone program #!/usr/bin/perl -w # dutree - print sorted indented rendition of du output use strict;
my %Dirsize; my %Kids;
getdots(my $topdir = input()); output($topdir);
# run du, read in input, save sizes and kids # return last directory (file?) read sub input { my($size, $name, $parent); @ARGV = ("du @ARGV |"); # prep the arguments while (<>) { # magic open is our friend ($size, $name) = split; $Dirsize{$name} = $size; ($parent = $name) =~ s#/[^/]+$##; # dirname push @{ $Kids{$parent} }, $name unless eof; } return $name; }
# figure out how much is taken up in each directory # that isn't stored in subdirectories. add a new # fake kid called "." containing that much. sub getdots { my $root = $_[0]; my($size, $cursize); $size = $cursize = $Dirsize{$root}; if ($Kids{$root}) { for my $kid (@{ $Kids{$root} }) { $cursize -= $Dirsize{$kid}; getdots($kid); } } if ($size != $cursize) { my $dot = "$root/."; $Dirsize{$dot} = $cursize; push @{ $Kids{$root} }, $dot; } }
# recursively output everything, # passing padding and number width in as well # on recursive calls sub output { my($root, $prefix, $width) = (shift, shift || '', shift || 0); my $path; ($path = $root) =~ s#.*/##; # basename my $size = $Dirsize{$root}; my $line = sprintf("%${width}d %s", $size, $path); print $prefix, $line, "/n"; for ($prefix .= $line) { # build up more output s//d /| /; s/[^|]/ /g; } if ($Kids{$root}) { # not a bachelor node my @Kids = @{ $Kids{$root} }; @Kids = sort { $Dirsize{$b} <=> $Dirsize{$a} } @Kids; $Dirsize{$Kids[0]} =~ /(/d+)/; my $width = length $1; for my $kid (@Kids) { output($kid, $prefix, $width) } } }
#----------------------------- # download the following standalone program #!/usr/bin/perl # dutree_orig: the old version pre-perl5 (early 90s)
@lines = `du @ARGV`; chop(@lines); &input($top = pop @lines); &output($top); exit;
sub input { local($root, *kid, $him) = @_[0,0]; while (@lines && &childof($root, $lines[$#lines])) { &input($him = pop(@lines)); push(@kid, $him); i} if (@kid) { local($mysize) = ($root =~ /^(/d+)/); for (@kid) { $mysize -= (/^(/d+)/)[0]; } push(@kid, "$mysize .") if $size != $mysize; } @kid = &sizesort(*kid); }
sub output { local($root, *kid, $prefix) = @_[0,0,1]; local($size, $path) = split(' ', $root); $path =~ s!.*/!!; $line = sprintf("%${width}d %s", $size, $path); print $prefix, $line, "/n"; $prefix .= $line; $prefix =~ s//d /| /; $prefix =~ s/[^|]/ /g; local($width) = $kid[0] =~ /(/d+)/ && length("$1"); for (@kid) { &output($_, $prefix); }; }
sub sizesort { local(*list, @index) = shift; sub bynum { $index[$b] <=> $index[$a]; } for (@list) { push(@index, /(/d+)/); } @list[sort bynum 0..$#list]; }
sub childof { local(@pair) = @_; for (@pair) { s/^/d+/s+//g; s/$; } index($pair[1], $pair[0]) >= 0; }
#-----------------------------
|