#!/usr/bin/env perl # mdf --- df wrapper to align columns for legibility # Author: Noah Friedman # Created: 2001-01-11 # Public domain. # $Id: mdf,v 1.7 2006/11/30 04:45:39 friedman Exp $ # Commentary: # Code: $^W = 1; # enable warnings use POSIX qw(uname); use Getopt::Long; use strict; my $domain = dnsdomain (); my $fieldsep = "[ \t]+"; my %right_justify = ( 1 => 1, 2 => 1, 3 => 1, 4 => 1); my $width_limit; # not currently used my $widthpad = 1; # extra padding to add between columns my $sortkey = 'mountpoint'; my %sortby = ( dev => 0, size => 1, device => q(dev), used => 2, '/dev' => q(dev), avail => 3, pct => 4, mnt => 5, percent => q(pct), mount => q(mnt), '%' => q(pct), mountpoint => q(mnt), 'use%' => q(pct), fs => q(mnt), 'used%' => q(pct), filesystem => q(mnt), ); sub dnsdomain { my @uname = uname (); my $nodename = $uname[1]; unless ($nodename =~ /\./) { use Socket; my $addr = gethostbyname ($nodename); $nodename = gethostbyaddr ($addr, AF_INET); } return undef unless ($nodename =~ /\./); $nodename =~ s/^[^.]+\.//; return $nodename; } sub parse_input ($$) { my $lines = shift; my $fieldsep = shift; my @parsedlines; my @maxwidth; for my $line (@$lines) { my @fields = split (/$fieldsep/o, $line, -1); push @parsedlines, \@fields; my $i = 0; for my $f (@fields) { my $l = length $f; $maxwidth[$i] = $l if (!defined $maxwidth[$i] || $l > $maxwidth[$i]); $i++; } } return \@parsedlines, \@maxwidth; } sub print_output ($$) { my ($lines, $maxwidth) = @_; my @fmts; my $i = 0; for my $width (@$maxwidth) { my $w = (defined $width_limit ? min ($width, $width_limit) : $width); push @fmts, join ("", $i == 0 ? "" : " " x $widthpad, (exists $right_justify{$i} ? "%" : "%-"), $w, (defined $width_limit ? "." . ($w-1) : ""), "s"); $i++; } $fmts[$#fmts] = "%s" if (substr ($fmts[$#fmts], 1, 1) eq '-'); my $fmtstr = join (" ", @fmts); for my $l (@$lines) { my $s = sprintf ($fmtstr, @$l); $s =~ s/\s+$//; print $s, "\n"; } } sub parse_options { local *ARGV = \@{$_[0]}; # modify our local arglist, not real ARGV. Getopt::Long::config (qw(auto_abbrev require_order pass_through)); GetOptions ("s|sort|sort-by=s" => \$sortkey, ); } sub atoi { local $_ = shift; s/^(\d+).*$/$1/; return 0 + $_; } sub main { parse_options (\@_); my $dfcmd = exists $ENV{DF} ? $ENV{DF} : 'df'; push @_, "-k" unless (scalar @_ > 0); my $dfout = qx{ $dfcmd @_ }; my ($header, $rest) = split (/\n/, $dfout, 2); $header =~ s/mounted on/Mountpoint/io; $header =~ s/available/Avail/io; $header =~ s/capacity/Use%/io; $rest =~ s/\n\s+/ /go; $rest =~ s=\.$domain:/=:/=go if (defined $domain); my ($lines, $maxwidth) = parse_input ([$header, split (/\n/, $rest)], $fieldsep); $header = shift @$lines; $sortkey = $sortby{lc $sortkey} while defined $sortkey && $sortkey !~ /^\d+$/; $sortkey = 5 unless defined $sortkey ; our (@a, @b); my $sortfn = ($right_justify{$sortkey} ? sub { atoi ($a->[$sortkey]) <=> atoi ($b->[$sortkey]) } : sub { $a->[$sortkey] cmp $b->[$sortkey] }); $lines = [sort $sortfn @$lines]; unshift @$lines, $header; print_output ($lines, $maxwidth); } main (@ARGV); # mdf ends here