Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

direcotories and spaced used

by nop (Hermit)
on Nov 06, 2000 at 21:23 UTC ( [id://40191]=perlquestion: print w/replies, xml ) Need Help??

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

Hi. I'm on a NT system. The only way I know to get the size of a folder is to right-click on it and ask for "properties". I'm looking for a simple (most likely perl?) way to get the size in K for each directory, each subdirectory, etc. Disk usage by user would be also be a plus.
Anyone have any perl to do this, before crafting my own?
nop
"life was simpler under unix..."

Replies are listed 'Best First'.
Re: direcotories and spaced used
by jjhorner (Hermit) on Nov 07, 2000 at 00:52 UTC

    Is there any reason you guys decided not to use the File::Find module?

    Proof of concept:

    #!/usr/bin/perl -w use strict; use File::Find; @ARGV = ('.') unless @ARGV; my $sum = 0; find sub { $sum += -s }, @ARGV; print "@ARGV contains $sum bytes\n";

    This will sum up the arguments and will print them back to you.

    I don't know if merlyn is still around, but he used to go nuts when people did recursive stuff like this.

    J. J. Horner
    Linux, Perl, Apache, Stronghold, Unix
    jhorner@knoxlug.org http://www.knoxlug.org/
    

      ...because that would be a pain. Programming via call-backs sucks. Now, if File::Find were to be totally rewritten instead of just being heavilly patched with lots of backward compatability, then there'd probably be an OO or other non-callback interface and I'd be less likely to roll my own replacement (I'd like to do this rewrite when I get more free time).

      Plus, File::Find out of the box fails on most systems I work on because the silly "count number of links to determine how many subdirectories" bad hack has remained long past its usefulness. So rolling my own works better than using File::Find. Now, this particular reroll has the common mistake of not detecting symbolic links to directories. I personally don't have any symbolic links to directories to worry about so this is not a problem for me but it would be good to fix this.

      One way to fix that would be to use File::Find, but I don't consider that the best way. File::Find's job just isn't tricky enough that you can't roll your own that is even better with a very small bit of work. Now, the symbolic link problem is found in almost all first versions of rewrites of File::Find. And before that, the problem of having to either prepend the directory-path-so-far or chdir() is found because otherwise the rewrite just doesn't work. So watch out for those at least.

              - tye (but my friends call me "Tye")
      Of course you're right, I'm just hoping that he doesn't decide to review all old posts when he comes back from his trip ;-).

      I think it all stems from the fact that there were no such thing as modules when I started with Perl (or at least not that I was aware of), and I took a lot of years off Perl (sounds of gasps from the shocked crowd) doing other assorted stuff until about a month ago...

      Albannach locks himself in his cell without his dinner and chants "use the modules" some more...

RE: directories and space used
by Albannach (Monsignor) on Nov 06, 2000 at 21:28 UTC
    Without bothering to think for myself (Monday and all |-), it appears that you could use this as a good starting point.
Re: direcotories and spaced used
by nop (Hermit) on Nov 06, 2000 at 21:45 UTC
    Thanks! I used Albannach's suggestion, though it seems I need to prepend the directory name explicitly. Anyway, the code below works... thanks gang!
    nop
    use strict; my $dir = shift; if (!$dir) {die "perl $0 [startdir]\n";} my %size; &dir_tree_size($dir); foreach my $dir ( map { $_->[1] } sort { $b->[0] <=> $a->[0] } map { [$size{$_}, $_ ] } keys %size) { print "$size{$dir}\t$dir\n"; } sub dir_tree_size { my $dir = shift; warn "$dir\n"; my ($i,$total); $total = 0; opendir DIR, $dir; my @files = grep !/^\.\.?$/, readdir DIR; for $i (@files) { if(-d $dir . "\\" . $i) { $total += &dir_tree_size($dir . "\\$i") } else { $total += -s $dir . "\\" . $i} } $size{$dir} = sprintf("%8d K", $total / 1024); return $total; }
      Seems to work nicely on this NT box. Since I hate warnings, I took the ' K' out of your sprintf() and added to your print line.

      Also, I don't think your return $total; does anything that wouldn't be done without it, does it?

      Update: Ok, count me stupid (I already mentioned Monday, right?)! I guess the non-summing result looked useful enough to me? Thanks for clearing that up for me nop!

      Just for the record, the result will be total of file size, not space used (the Windows Properties box reports both values).

      Without the  return $total, directories don't inherit the size of their subdirectories... without it, the
      $total += &dir_tree_size($dir . "\\$i")
      does nothing....

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://40191]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-03-29 09:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found