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

What am I missing? I want to remove all the files on a volume that are older than 30 days. The first step is to find them. In sh I say:

find /backup -mtime +30

In perl I say:

#!/usr/bin/perl -w use strict; my $dir = $ARGV[0]; my $thirty_days_ago = time() - ( 30 * 24 * 60 * 60 * 60 ); my @files; use File::Find; find( \&wanted, $dir ); sub wanted { my @stats = (); # ignore symlinks if ( !-l $_ ) { @stats = stat($_) or warn "couldn't stat $_\n"; } # 9 is mtime; if ( !-l $_ && $stats[9] < $thirty_days_ago ) { push @files, "${File::Find::dir}/$_"; } } print join ( "\n", @files ), "\n";

email: mandog

Replies are listed 'Best First'.
Re: (1) line of sh vs (~20) lines of perl ?
by broquaint (Abbot) on Nov 18, 2002 at 16:09 UTC
    While this is a perfect job for the shell, perl can still pull off a one liner
    perl -MFile::Find::Rule -e 'unlink find(file => mtime => 86400 * 30,in => shift)' /backup
    Well nearly one-line :)


    update: dropped the for, as Aristotle rightly points out unlink can take a list

      You can leave the for off that. unlink takes more than one parameter at a time.

      Makeshifts last the longest.

Re: (1) line of sh vs (~20) lines of perl ?
by VSarkiss (Monsignor) on Nov 18, 2002 at 16:07 UTC

    You're not missing anything. Just use the right tool for the job.

    The main difference is that the Perl version can be easier to port to Win32, VMS, OS X, and so on, whereas the shell script (really the find program) may not be available, or may work differently (find on Win32 is a whole 'nuther program).

Re: (1) line of sh vs (~20) lines of perl ?
by Thelonius (Priest) on Nov 18, 2002 at 16:12 UTC
    #!/usr/bin/perl -w use File::Find; find( sub { print "$_\n" if !-l && -M > 30 }, @ARGV);
    Or, on the command line,
    perl -MFile::Find -le 'find( sub { print if !-l && -M > 30}, @ARGV)'
(z) Re: (1) line of sh vs (~20) lines of perl ?
by zigdon (Deacon) on Nov 18, 2002 at 15:59 UTC
    May I suggest that if that's the only thing you need to do here, shell might be the better tool for the job?

    -- Dan

Re: (1) line of sh vs (~20) lines of perl ?
by perrin (Chancellor) on Nov 18, 2002 at 16:04 UTC
    No need to make it so difficult, if that's all you want to do.

    system('find /backup -mtime +30');
Re: (1) line of sh vs (~20) lines of perl ?
by waswas-fng (Curate) on Nov 18, 2002 at 17:22 UTC
    find <dir> -mtime +30 -exec rm {} \;
    No need for perl here let find do its job. =)

More like 1 line of sh vs 1 line of perl
by buckaduck (Chaplain) on Nov 18, 2002 at 21:27 UTC
    VSarkiss mentioned it parenthetically, but it needs to be emphasized: your "one line of sh" is really just an invocation of a much larger program called "find". You could do the same thing in Perl with system or exec commands.

    The interesting thing is that with Perl you created your own program to find the files for you. And it seems that you did it quickly, easily, and portably -- in just a few lines of code (even fewer for some of the respondents). And if you wanted to, you could extend the program to perform tests that aren't easy to do with "find" (e.g. "File owner matches a record in an Oracle database"). You could do that with sh, but would you want to?

    So what are you missing? Some respect for what you just accomplished, and for the language that makes it possible.


Re: (1) line of sh vs (~20) lines of perl ?
by grantm (Parson) on Nov 19, 2002 at 09:00 UTC

    I'm not going to try to turn your script into a one-liner (smarter people already have) but you could trim down your original script using the '-M' function

    push(@files, "${File::Find::dir}/$_") if(!-l $_ and (-M $_) > 30);

    Note, I'm sorry I haven't tested this but it should work