This snippet executes du in the current directory and parses the output into a hash. For example, if du produces this:
96 ./m4 6280 ./po 368 ./intl 1968 ./doc 512 ./contrib 32 ./charmaps 440 ./imap 14896 .
then my snippet will produce a %dirs hash that looks like this:
( '.' => { 'blocks' => 14896, 'dirs' => { 'imap' => { 'blocks' => 440 }, 'm4' => { 'blocks' => 96 }, 'charmaps' => { 'blocks' => 32 }, 'po' => { 'blocks' => 6280 }, 'contrib' => { 'blocks' => 512 }, 'doc' => { 'blocks' => 1968 }, 'intl' => { 'blocks' => 368 } } } )
open DU, 'du .|' or die "Couldn't open du: $!"; while (<DU>) { ($blocks, $_) = split; s:/:'}{dirs}{':g; eval "\$dirs{'$_'}{blocks} = $blocks" } close DU;

Replies are listed 'Best First'.
RE: "du" to hash
by merlyn (Sage) on Jul 04, 2000 at 11:42 UTC
    I really really dislike the eval there. How about this instead?
    use strict; use Data::Dumper; my %blocks; for (`du`) { (my $blocks, my $rest) = split; my @dirs = split /\//, $rest; my $where = \%blocks; while (@dirs) { $where = ($where->{shift @dirs} ||= {}); } $where->{""} = $blocks; } print Dumper(\%blocks);
    The hash element with an empty string (an illegal directory name, important here) is the sum total of everything below it.

    -- Randal L. Schwartz, Perl hacker

      First off, love the for loop. I didn't think of that. Out of curiosity, why do you dislike the eval? Just because evals are generally evil?

      *Woof*

        Two reasons to dislike the eval come to mind immediately:
        1. You are firing up the compiler over and over again to parse Perl code, when in fact the only part that is changing is the indicies and the depth of those. That means you're using a very general pile of code to handle a well-known predictable subset, and you'll burn far too much CPU to do that in the long run.
        2. More specifically here, you aren't escaping things like ` and { in the directory names, so you'll get invalid compilations from time to time, which you aren't checking for. These could also be potential security holes, since I merely have to create a directory with a name like `my-proggy` and you'll now be executing it! Shame.
        I consider any use of runtime eval to be a red flag during a code review session. There really has to be no other way to do something, and let me tell you, there's almost always more than one better way to do it.

        -- Randal L. Schwartz, Perl hacker

RE: 'du' to hash
by le (Friar) on Jul 04, 2000 at 11:11 UTC
    Sorry for asking a really stupid question, but what does this line do? Yes, it's a regexp, but I can't figure out what it does....
    s:/:'}{dirs}{':g;
    Another question: will this work for sub-sub-dirs?

      It's a substitution, but it looks a bit strange because it's using ':' as the separator instead of the more usual '/'. This is because '/' is the character that is being replaced, so using a different separator avoids having to escape it.

      In summary, the line looks for all occurances of '/' in $_ and replaces them with '}{dirs}{'.

      --
      <http://www.dave.org.uk>

      European Perl Conference - Sept 22/24 2000
      <http://www.yapc.org/Europe/>