Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

more ways to filesize

by d4vis (Chaplain)
on Aug 06, 2002 at 00:19 UTC ( [id://187869]=perlquestion: print w/replies, xml ) Need Help??

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

Hullo,
I whipped this together 5min. ago, but would like a little help cleaning it up.
I need to scan multiple sendmail inboxes (/usr/home/<username>/INBOX) for size, and return a list of those over a certain limit.
It seemed the best way was to just pull the usernames from a list I generated with ls, then run the following:

#!/usr/local/bin/perl -w use strict; open (FH, "userlist") || die "no userlist: $!"; open (FH2, ">output") || die "no output file: $!"; while (<FH>) { chomp; my $file = ("/usr/home/$_/INBOX"); my $maxsize = (30000*1024); if (-s $file) { my $size = (stat $file)[7]; my $meg = int ($size / 1024000); if ($size > $maxsize) { printf "%25s %3sMB\n", $_,$meg; print FH2 "$_:$meg\n"; } } } close (FH) || die "couldn't close userlist: $!:"; close (FH2) || die "couldn't close output: $!";

The chunk works just fine, but I'd like suggestions on how to make it better/stronger/faster, etc...
Is this even the right approach?
What do you think?

-thanks

~monk d4vis
#!/usr/bin/fnord

Replies are listed 'Best First'.
(jeffa) Re: more ways to filesize
by jeffa (Bishop) on Aug 06, 2002 at 00:44 UTC
    tstock gave you some good refactoring ideas, how about some good formatting ideas? I ran your code through perltidy:
    #!/usr/local/bin/perl -w use strict; open( FH, "userlist" ) || die "no userlist: $!"; open( FH2, ">output" ) || die "no output file: $!"; while (<FH>) { chomp; my $file = ("/usr/home/$_/INBOX"); my $maxsize = ( 30000 * 1024 ); if ( -s $file ) { my $size = ( stat $file )[7]; my $meg = int( $size / 1024000 ); if ( $size > $maxsize ) { printf "%25s %3sMB\n", $_, $meg; print FH2 "$_:$meg\n"; } } } close(FH) || die "couldn't close userlist: $!:"; close(FH2) || die "couldn't close output: $!";
    With the original code i really had to squint to notice that you were indeed unecessarily calculating the max size inside the while loop.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: more ways to filesize
by tstock (Curate) on Aug 06, 2002 at 00:30 UTC
    Once you stat a file (by either using the stat function or the -s thingy) you can get to the stat structure by using the special filehandle '_' (underscore). Using this you avoid more than one stat for each file.
    if (-s $file) { my $size = (stat _)[7];

    Another thing to keep in mind, although not very important here, is to keep your loops small. the (30000*1024) constant doesn't need to be calculated everytime.

    By the same token, you only need to int() your $meg if you are going to print it out, and since you are using printf, you don't even need it there.

    Tiago
      Well actually, instead of this:
      if (-s $file) { my $size = (stat _)[7]; }
      I tend to prefer this:
      my $size = ( -s $file );
      because the -s returns the file size in bytes. If you want anything else from stat along with the file size, then check "perldoc -f stat" to recall how stat orders things, and do something like this:
      my ($mode,$uid,$size,$modtime) = (stat $file)[2,4,7,9];
      And I agree with Jeffa -- perltidy is a Blessing To Us All, because proper indentation is every programmer's friend.

      BTW, slight correction. The multipication is only done once, at compile-time. OTOH, the result doesn't need to be assigned to a variable every time through the loop. In fact, even better, it doesn't need to be assigned to a variable at all; use constant MAXSIZE => 30000*1024 at the top. Even better, 30*1024*1024, which is probably what you meant.


      Confession: It does an Immortal Body good.

Re: more ways to filesize
by DamnDirtyApe (Curate) on Aug 06, 2002 at 05:33 UTC

    Here's my version; I made some changes that I thought cleaned things up a little:

    1. This version uses readdir to get the list of home directories, so you can avoid creating a temporary file with ls first;
    2. The output goes to STDOUT only. I think that, since your on a *nix machine, you'll find it advantageous not to send your output to a hard-wired data file. If you want your output to go to the screen and a file simultaneously, use the tee command; eg.
      perl my_script.pl | tee my_logfile.dat
    3. I know this code rather contradicts the quote in my sig, but I couldn't help it. It was too much fun rebuilding the processing into one line. Sorry.
    #! /usr/bin/perl use strict ; use warnings ; $|++ ; use Data::Dumper ; my $home_root = '/usr/home' ; my $size_limit = 30 * 1_024_000 ; opendir HOME, $home_root or die "Couldn't open $home_root: $!" ; printf "%-25s | %3.2fMB\n", $_->[0], $_->[1] / 1_024_000 for grep { $_->[1] > $size_limit } map { [ $_ => ( stat "$home_root/$_/INBOX" )[7] || 0 ] } grep { -d "$home_root/$_" } readdir HOME ; closedir HOME ; exit ; __END__

    _______________
    DamnDirtyApe
    Those who know that they are profound strive for clarity. Those who
    would like to seem profound to the crowd strive for obscurity.
                --Friedrich Nietzsche
Re: more ways to filesize
by sauoq (Abbot) on Aug 06, 2002 at 00:54 UTC
    if (-s $file) { my $size = (stat $file)[7];

    That would be better written as: my $size = -s $file;

    See perlfunc for documentation of the fact that -s returns the size of the file (in bytes.)

    Update: (Answering Chmrr's reply below...)

    my $size = -s $file; if ($size) { . . . }
    -sauoq
    "My two cents aren't worth a dime.";
    

      Actually, it's probably better written as:

      if (my $size = -s $file)

      ..or, if you don't like the assignment in the if, you can keep the (oh-so-slight..) efficiency increase by saying:

      if (-s $file) my $size = -s _;

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-03-29 00:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found