Revision 76 (by dpavlin, 2008/04/08 21:05:42) added -h to produce human-readable output
#!/usr/bin/perl -w

use strict;
use Term::ReadKey qw(GetTerminalSize);
use Getopt::Long;

my $human = 0;
GetOptions(
	'human!' => \$human,
);

my @lines;

my $max_size = 0;
my $max_sum = 0;
my $rest_len = 0;
my $sum = 0;

my @units = qw/b k M G/;
sub unit {
	my $v = shift;

	return $v unless $human;

	my $o = 0;

	while ( ( $v / 10000 ) >= 1 ) {
		$o++;
		$v /= 1024;
	}

	if ( $v >= 1 ) {
		return sprintf("%d%s", $v, $units[$o]);
	} elsif ( $v == 0 ) {
		return 0;
	} else {
		return sprintf("%.1f%s", $v, $units[$o]);
	}
}

while(<>) {
	chomp;
	if (/\s*([\d\.]+)\s+(.+)/) {
		my ($size,$rest) = ($1,$2);
		$sum += $size;
		$max_size = $size if ($size > $max_size);
		$max_sum = $sum if ($sum > $max_sum);
		my $rl = length($rest);
		$rest_len = $rl if ($rl > $rest_len);
		push @lines, [ $size, $rest, $sum ];
	} else {
		print STDERR "# $_\n";
	}
}

my $cols = eval { (Term::ReadKey::GetTerminalSize)[0] } || $ENV{COLS} || $ENV{COLUMNS} || 80;

# convert to chars
my $size_len = length($max_size);
my $sum_len = length($max_sum);

my $bar_size = $cols - $rest_len - $sum_len - $size_len - 4;

sub bar_size {
	my ($v,$m) = @_;
	return int($v * $bar_size / $m)
}

sub bar {

	my ($v1,$m1,$v2,$m2) = @_;
	my $b1 = bar_size($v1, $m1);
	my $b2 = bar_size($v2, $m2);

	my $bar = '';

	if ($b1 < $b2) {
		$bar .= "O" x $b1;
		$bar .= "-" x ($b2 - $b1);
	} elsif ($b1 > $b2) {
		$bar .= "*" x $b2;
		$bar .= "-" x ($b1 - $b2);
	} else {
		$bar .= "O" x $b1;
	}
}

foreach my $l (@lines) {
	my ($size,$r,$tmpsum) = @{$l};
#	printf "%-50s\t[ + %-8d= %-8d ]\n",$r,$size,$tmpsum;
	printf "%-${rest_len}s %${size_len}s %-${bar_size}s %${sum_len}s\n",
		$r, unit($size), bar($size, $sum, $tmpsum, $sum), unit($tmpsum);
}