Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

du with backticks

by Panasonictoilet (Initiate)
on Mar 20, 2008 at 00:21 UTC ( #675134=perlquestion: print w/ replies, xml ) Need Help??
Panasonictoilet has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks,

I am trying to write a script that goes through home directories and does a du but excludes stuff in specific Maildir directories, cur, new, tmp and courierimapkeywords. I have tested it on the commandline and I have it in my perl script as below:

$du=`du -ch $homedir | grep -v '^.*Maildir.*cur$' | grep -v '^.*Maildir.*tmp$' | grep -v '^.*Maildir.*new$' | grep -v '^.*Maildir.*courierimapkeywords$'`; print $du;

However this does not work and is giving me the following errors:

du: cannot access `~skim': No such file or directory sh: .*Maildir.*tmp: not found sh: .*Maildir.*courierimapkeywords: not found

I have used backticks before for simple operations but is this too complicated for backticks, or do i need to escape certain character out, if so how??

Please help enlighten me fellow monks!

Comment on du with backticks
Re: du with backticks
by JStrom (Pilgrim) on Mar 20, 2008 at 01:15 UTC

    You're interpolating $' into your string in quite a few places. I doubt that's what you wanted. Try escaping those $ s in the grep commands.

    You might find it easier to dispense with the pipline all together. readpipe (i.e. the backticks) returns a list of the lines read when in list context so you could write:

    print grep $_ !~ /^.*Maildir.*cur$/, grep ..., readpipe "du -ch $homedir";

Re: du with backticks
by snoopy (Deacon) on Mar 20, 2008 at 01:18 UTC
    Maybe it's time consider refactoring this via CPAN modules? For comparison, the following achieves a similar result, using File::Find::Rule and Filesys::DiskUsage:
    #/usr/bin/perl use warnings; use strict; use Filesys::DiskUsage qw/du/; use File::Find::Rule; use YAML; my $rule = File::Find::Rule->new; $rule->directory(); $rule->not($rule->new->name( qr/^.*Maildir.*(cur|new|courierimapkeywor +ds)$/)); my @dirs = $rule->in('.'); warn "dirs=@dirs"; my %sizes = du( { 'make-hash' => 1, 'human-readble' => 1, } , @dirs); print YAML::Dump(\%sizes);
Re: du with backticks
by blahblahblah (Priest) on Mar 20, 2008 at 01:35 UTC
    The first error message, du: cannot access `~skim': No such file or directory, made me curious. I think that if you reduce your program to a very simple command you'll find that it's not running from the right directory or that ~skim doesn't exist?
    my $homedir = '~bogus'; $du=`du -ch $homedir`; print "$du";
    produces a similar message for me:
    ./test du: cannot access `~bogus': No such file or directory 0 total
Re: du with backticks
by pc88mxer (Vicar) on Mar 20, 2008 at 05:09 UTC
    This is not your problem, but it might be of interest to know that ~-expansion is actually done by the shell. So, even though the following calls look like they do the same thing, the first two work as expected, but the last one doesn't:
    `du ~user`; system("du ~user"); system("du", "~user"); # doesn't work
    Generally you are better off calling getpwnam() to get a user's home directory instead of using ~user.
    my $user = ...; my $home = (getpwnam($user))[7]; system("du", $home); # etc.
Re: du with backticks
by graff (Chancellor) on Mar 20, 2008 at 08:22 UTC
    IMO, when you need to "grep" stuff, you're better off doing it in perl. I'm agnostic about shell "du" vs. perl-module solutions for the same thing, but stringing a bunch of separate "grep" commands in a pipe like the OP does is just ugly and so unnecessary. I'd be content with something like this (not tested):
    $du = join( '', grep !/^.*?Maildir.*?(?:cur|tmp|new|courierimapkeywords)$/ +, `du -ch $homedir` ); print $du;
    Anything you can do to shorten/constrain/simplify the stuff in backticks is generally a good idea, esp. in terms of eliminating "shell-magic" characters as much as (or completely if) possible.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2014-10-20 23:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (93 votes), past polls