du alternative in perl

I have a perl script that just does a `du -sk -x` and formats it to look groovy ( the argument can be a directory but usually is like /usr/local/* )

#!/usr/bin/perl

use strict;
use warnings;

my $sizes = `du -x -sk @ARGV | sort -n`;
my $total = 0;

print "MegaBytes Name\n";
for(split /[\r\n]+/,$sizes)                     #split on one or more newline characters
{
        my($number,$file) = split /\t/,$_,2;    #split on tab ($file not used here)
        my $number1 = sprintf ("%9.2f",$number / 1024);
        printf "$number1 $file\n";
        $total += $number;
}

printf ("TOTAL: %9.2f\n",$total / 1024);

The script works fine and does all that i want it to and i use it all the time, however is there an internal perl function that could replace the du -sk -x? I am just curious and would like to have a pure perl script with no shell options (primarily because the du options are not standard across the UNIX/Linux world). This is on a RHEL box just FYI. An external module might work too, if i can get them to let me install it.

Sean

du depends heavily on stat - which is POSIX. So writing C code is failry portable,
along with the dirent.h functions

perl implements stat, so that's cake. The other needed calls: closedir, opendir, and readdir to get file names to stat. Both of those are in perl as well.... go for it.

Perl by Example has an example getting all the file names in a directory.

This does something else with stat data as entry-level example code for the forums here, but you can clean it up for your use:

#!/usr/bin/perl 
    use strict;
	sub numeric;
	sub to_date;
	my @filelist = ();
	my @sortarray = ();
	my $idx = 0;
	my $value = "";
	my $file = "";
	opendir(DIR, "..") || die "can't open $!\n";
	@filelist = readdir(DIR);
	closedir(DIR);

	$idx = 0;
	@sortarray = ();
	foreach $file ( @filelist )
	{
		$sortarray[$idx] = sprintf("%d %s", (stat "../$file")[9], $file);
		$idx++;
	}

	@filelist = sort numeric @sortarray ;
    print "@filelist\n";
	foreach $value ( @filelist )
	{
		print &to_date( $value );
	}

	sub numeric { my @one = split(' ', $a);
		          my @two = split(' ', $b); 
		          return $one[0] <=> $two[0];
		        }
	sub to_date {
		 my @months = ();
		 my $filename = "";
		 my $mtime = 0;
		 my $sec = 0; 
		 my $min = 0; 
		 my $hr = 0;
		 my $mday = 0; 
		 my $mon = 0; 
		 my $yr = 0; 
		 my $wday = 0; 
		 my $yday = 0; 
		 my $dntcare =0;
		 my $retval = "";
		 
		 @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);

         ($mtime, $filename) = split(' ', $_[0]);	     
	     ($sec, $min, $hr, $mday, $mon, $yr, $wday, $yday, $dntcare) =
	         localtime($mtime);
	     $retval = sprintf( "%-10s %3s %02d %4d %02d:%02d:%02d\n",
	         $filename, $months[$mon], $mday, $yr + 1900, $hr, $min, $sec );

         return $retval;
	}