gopalr has asked for the wisdom of the Perl Monks concerning the following question:

Hi Esteemed Monk,

c:\temp c:\temp\file1.txt c:\temp\file2.txt c:\temp\Folder_1\file1.txt c:\temp\Folder_2\file1.txt

The above 'c:\temp' folder contains Files and Subdirectories.

I need the Total Files Size and No. of Total Files contains in 'c:\temp' Directory?

And also, which files is largest?

Thanks in Advance.

Regards,

Gopal.R

Replies are listed 'Best First'.
Re: Get the Total Size & Total Files in a Directory
by Aristotle (Chancellor) on Jan 12, 2005 at 12:37 UTC

    use File::Spec::Functions qw( no_upwards ); use File::Find; use List::Util qw( sum ); my ( $num, $size ); find( { preprocess => sub { my @l = no_upwards( @_ ); $num += @l; $size += sum map -s, @l; return @_; }, wanted => sub {}, }, "foo/bar/" );

    Makeshifts last the longest.

      The advice "don't roll your own solution - use a module" applies to system utilities as well. Perhaps even more so. Your solution is wrong, as it doesn't take links into account.
      #!/usr/bin/perl use strict; use warnings; use File::Spec::Functions qw( no_upwards ); use File::Find; use List::Util qw( sum ); my $dir = "foo/bar"; # # Clear directory if it exists. # system "rm", "-rf", $dir and die; # # Create new directory # system "mkdir", "-p", $dir and die; # # Create big file. # system "dd", "if=/dev/zero", "of=$dir/big1", "bs=8096", "count=1024" a +nd die; # # Create a link # link "$dir/big1", "$dir/big2" or die "link: $!"; # # Calculate size by Aristotle method: # my ( $num, $size1 ); find( { preprocess => sub { my @l = no_upwards( @_ ); $num += @l; $size1 += sum map -s, @l; return @_; }, wanted => sub {}, }, $dir ); # # Calculate size by not rolling your own: # my ($size2) = `du -b $dir` =~ /\d+/g; printf "System thinks size equals %d kbytes, Aristotle thinks %d kbyte +s\n", $size2 / 1024, $size1 / 1024; __END__ 1024+0 records in 1024+0 records out System thinks size equals 8130 kbytes, Aristotle thinks 16192 kbytes
      And the existance of hardlinks isn't the only thing your solution gets wrong.

        Er, the only problem here is that by the OPs stating he has files in the directory c:\temp\ we can infer it is a windows machine: a) it is unlikely that the system utilities you suggest are available on windows. b) there aren't hard links on windows so the problem wouldn't arise in the first place.

        /J\

        A reply falls below the community's threshold of quality. You may see it by logging in.
        --- t.pl.orig 2005-01-12 23:49:42.000000000 +0100 +++ t.pl 2005-01-12 23:53:06.000000000 +0100 @@ -4,0 +5,6 @@ +sub blocksize { + my $fname = @_ ? $_[ 0 ] : $_; + my @s = ( stat $fname )[ 11, 12 ]; + return $s[ 0 ] * $s[ 1 ]; +} + @@ -8 +14 @@ - my @l = no_upwards( @_ ); + my @l = grep -f || -d, no_upwards( @_ ); @@ -10 +16 @@ - $size += sum map -s, @l; + $size += sum map blocksize(), @l;

        Makeshifts last the longest.

Re: Get the Total Size & Total Files in a Directory
by gellyfish (Monsignor) on Jan 12, 2005 at 10:47 UTC

    You will want to use the File::Find module and the -s operator (or stat)

    /J\

      Be careful though. File::Find will report any occurence of a filename. Even if the same file has many names (links). Just summing up the -s results from whatever File::Find reports may not give you the total size of a directory.
Re: Get the Total Size & Total Files in a Directory
by zentara (Cardinal) on Jan 12, 2005 at 13:55 UTC
    I am not clear whether you want to recurse into the subdirs or not? From your exact wording, I'm guessing you don't want to recurse, and only read files in c:\temp. This will get you size total and count, without recursion.
    #!/usr/bin/perl -w use File::Find; use strict; my $total = 0; my $count = 0; my $largest = 0; my $lfile; my $dir = $ARGV[0] || '.'; find sub { return if -l or -d; # comment out these 2 lines to recurse my $n = ($File::Find::name) =~ tr!/!!; #count slashes return $File::Find::prune = 1 if ($n > 1); #no subdirs $total += -s $_; $count++; if( (-s $_) > $largest){ $largest = -s $_; $lfile = $_} },$dir; my $megs = sprintf "%5.2f",($total/(1024*1024)); print "Total size of $count files in $dir:$megs Mbytes\n"; print "Largest file is $lfile at $largest\n";

    I'm not really a human, but I play one on earth. flash japh
Re: Get the Total Size & Total Files in a Directory
by blazar (Canon) on Jan 12, 2005 at 15:22 UTC
    #!/usr/bin/perl -l use strict; use warnings; use File::Find; @ARGV=grep {-d or !warn "`$_': not a directory!\n"} @ARGV; die "Usage: $0 <dir> [<dirs>]\n" unless @ARGV; my ($tot,$maxsz,$max,$n)=(0,0); find { no_chdir => 1, wanted => sub { return unless -f; $n++; $tot += my $sz=-s; ($max,$maxsz)=($_,$sz) if $sz >= $maxsz; } }, @ARGV; die "Found 0 files\n" unless $n; print <<"EOF"; Total files found: $n Total size: $tot Largest file: `$max' (size: $maxsz bytes) EOF __END__
Re: Get the Total Size & Total Files in a Directory
by bmann (Priest) on Jan 12, 2005 at 18:21 UTC
    And in the spirit of TIMTOWTDI, here's my take using OLE and the Windows Scripting FileSystemObject.

    It'll find the total size of the folder very quickly (useful by itself), then iterates through the files. Error handling not included ;)

    #!perl -l use warnings; use strict; use Win32::OLE qw/in/; die "Usage: $0 [dir]" unless (!@ARGV || -d $ARGV[0]); my $fs = Win32::OLE->CreateObject('Scripting.FileSystemObject'); my ($count, $maxname); my $max = 0; my $dir = shift || 'c:/temp'; my $fold = $fs->GetFolder($dir); print $fold->Size(), " total bytes used"; folders( $dir ); print "$count total files, $maxname = $max"; sub folders { my $dir = shift; my $fold = $fs->GetFolder( $dir ); foreach my $file ( in $fold->Files ) { my $size = $file->Size(); if ( $size > $max ) { $max = $size; $maxname = $file->Name; } $count++; } foreach my $subdir ( in $fold->SubFolders ) { folders( $subdir ); } }