How to calculate file's size in directory and subdirectory

Hi,

I have written one script to calculate total space of all file in one directory, ignoring subdirectory, it works fine.

Now, I've been trying to calculate all files which includes files in any subdirectories.

I use recursive function to do this, but it can work only if there is only one subdirectory right after the parent directory, but not more than 2 subdirectories. What i meant is:

parent A --> Sub I --> Sub I1 --> sub I2

The above will works fine as long as all other sub directories are inside Sub I

But if I have another subdirectory as same level as Sub I's, my script wont work correctly:

parent A
--> Sub I --> Sub I1 --> sub I2
--> Sub II --> Sub II2 ......

my script would't work, it can still calculate for space taken by Sub I, but it can't do for SubII. It doesn't recognize SubII as a subdirectory.

Here is the code that I have written:

Thanks a lot

I think I spot 2 general problems with your algorithm

The recursion is greedily depth first, that is, it never unwinds from traversing the first (and only) directory it encounters.

Secondly the 'total' value you use to keep a running count is useless because it is limited in scope to the call to search.

You need to

1) deal with breadth, enumerate all dirs at one level on each descent and keep them somewhere to explore later

2) pass back your total as a return value and deal with it

Knuth deals with all the standard well known tree traversal methods, see if you can research from there to get a better idea.

personal opinion:
Although recursion is 'divine' , its usually a lot less assache to go at it with a good ole sledgehammer.

KLL, please click on the rules link at the bottom of the page and read our rules. Notice what rule 6 says about classwork.

This looks like a homework assignment. If it's not, just do this:

du -sk /some/directory

Edit...

Some followups were posted discussing my above post. I split them off into a new thread which is here.

Thanks Andy.

Hi,

I know that it is a very long time since, but I found this thread and I think it might interest you.

Regs David

dirinfo.pl
#----------------------------------------------------------------------------------

#!/opt/perl/bin/perl

use File::Find;

# Determine wether argument is given or not
# -----------------------------------------
if (@ARGV) {
@dirm = @ARGV;
foreach $dirm(@dirm) {
if ($dirm eq "\." ) {
$dirm = `pwd`;
$dirm =~ s/\n//g;
}
$dirm =~ s/\/$//g;
push(@directory, $dirm);
}
}
else {
usage();
}
# -----------------------------------------

# Define global vars and hashes
# -----------------------------------------
%seen = ();
$total = ();
$nr = 0;
$mbnr = 0;
# -----------------------------------------

# Searching starting at your given directory
foreach $directory (@directory) {
finddepth(\&wanted, $directory);
}

# If this is dir is unique, start getting total disk usage inclusive sub-dirs
# -----------------------------------------
sub wanted {
$dir = "$File::Find::dir";

unless ($seen{$dir}++) {
next if ( $dir =~ lost+found );
next if ( $dir eq $directory );
$dm=`du -ks $dir 2>/dev/null`;
($kb, $path) = split /\s+/, $dm ;
$mb = int( $kb / 1024 );

$output\{$path\} = $mb;

}
}
# -----------------------------------------

# Determine most characters of path and store it in $nr
# -----------------------------------------
@long = keys %output;
foreach $item(@long) {
if ( $nr < length($item)) {
$nr = length($item);
}
}
# -----------------------------------------

# Determine most characters of size and store it in $mbnr
# -----------------------------------------
@long = values %output;
foreach $item(@long) {
if ( $mbnr < length($item)) {
$mbnr = length($item);
}
}
# -----------------------------------------

# Add a space as long as the the current path is smaller then the longest one.
# -----------------------------------------
print "\n\n\n";
while (($key, $value) = each %output) {
$numb = ( $nr - length($key) );
$mbnumb = ( $mbnr - length($value) );
$dd = " Directory $key has";
while ( $numb > 0 ) {
$dd = $dd . " ";
$numb--;
}
while ( $mbnumb > 0 ) {
$dd = $dd . " ";
$mbnumb--;
}
push(@newarray, "$dd $value Mb\n");
}
# -----------------------------------------

# Print total directory size
# -----------------------------------------
foreach $line(sort(@newarray)) {
print $line;
}

print "\n\n";

foreach $directory(@directory) {
$total=`du -ks $directory 2>/dev/null`;
($total_size, $useless) = split /\s+/, $total;
$total_size_mb = int( $total_size / 1024 );
print "Total usage of $directory is $total_size_mb Mb\n";
}
print "\n\n";
# -----------------------------------------

sub usage() {
print "\ndirinfo.pl: Error incorrect usage \n\n";
print "Usage: /usr/local/bin/dirinfo.pl <directory> \n";
print "\t <directory> Is directory start point to check \n\n\n";
exit 1;
}