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

Hi Monks!
I an trying to have my code looking in a specific directory or directories for file(s) that are the oldest of all the other files found in that specific directory. After that I need to delete the oldest file found.
My code now can find the age of all the files, but how can I delete de oldest file(s) found inside this directory(ies)?
Thanks for the help!!!

#!/perl/bin/perl -w use strict; use warnings; use Win32; use Win32::NetResource; use Time::localtime; my ($dirh,$dirh_in, @dircontent, $file, @filenames, $age, @outputFiles + , $all_dir_path); $age=''; $dirh_in=''; my $path='C:\\files\\logs'; opendir(DIRH, "$path") || die "Cannot opendir $path: $!"; foreach $dirh (sort readdir(DIRH)) { $all_dir_path= $path."\\".$dirh; $all_dir_path=~s/(.*?)\.+//g; if($all_dir_path ne ""){ chomp($all_dir_path); opendir $dirh,$all_dir_path or die "Can't open - Check Path + - $all_dir_path"; push (@dircontent, map { $_="$all_dir_path/$_"; $_;} rea +ddir($dirh)); closedir($dirh) or die "Can't close $path"; } } closedir(DIRH) or die "Can't close $path"; foreach (@dircontent) { next unless -f; # ignore all non-normal files. $age=-M $_; if($age){ unlink($_) || die "Cannont unlink $_: $!"; print "$_ - $age\n"; } }

Replies are listed 'Best First'.
Re: Deleting by Age!
by Zaxo (Archbishop) on Jun 23, 2006 at 14:38 UTC

    It's simpler than that with glob, default arguments, and a little logic.

    for (glob "$path/*">) { unlink if -f and -M _ > $cutoff; }
    That takes advantage of $_ as default argument for -X and unlink. The "_" handle saves a stat call.

    That omits the tree expansion, which is easily handled by wrapping in a recursive sub.

    (Added)

    sub unlink_all ( my ($path, $cutoff) = @_; local $_; for (glob "$path/*") { unlink, next if -f and -M _ > $cutoff; unlink_all($_, $cutoff) if -d _; } 1; }

    After Compline,
    Zaxo

Re: Deleting by Age!
by McDarren (Abbot) on Jun 23, 2006 at 14:41 UTC
    merlyn has an article that pretty much covers this. It's actually an excellent article, and a good introduction to File::Find and directory recursion.

    Thoroughly recommended!

    Cheers,
    Darren :)

Re: Deleting by Age!
by ptum (Priest) on Jun 23, 2006 at 14:30 UTC

    I think a combination of File::Find and File::stat (with use of the mtime method) may do the trick.


    No good deed goes unpunished. -- (attributed to) Oscar Wilde
Re: Deleting by Age!
by leocharre (Priest) on Jun 23, 2006 at 14:39 UTC

    sort it by age, reverse it, and shift the first filename from the array, then unlink it.

    If you are doing a stat and you have a ton of files, consider first getting all the stat into into a hash for all the files, then sorting, otherwise your sort will be running multiple stat for each file. Which is slow on a ton of files.

Re: Deleting by Age!
by shmem (Chancellor) on Jun 23, 2006 at 14:46 UTC
    Is this the script that you use for this task? What do you get as output? I guess it dies at line 26 saying something like Can't use string ("whatever") as symbol ref while "strict refs" in use.

    What do you get? Could you post the error messages along with "it doesn't work?"

    You do

    use Win32; use Win32::NetResource; use Time::localtime;
    but you do not use anything of those modules whatsoever. What gives? Along with the poor formatting it makes one setence of a professor spring into my mind: "Not only is this all incomprehensible, but the ink is ugly, and the paper is from the wrong kind of tree." ;-)

    Please post the output of that script.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Deleting by Age!
by InfiniteSilence (Curate) on Jun 23, 2006 at 19:29 UTC
    I think Zaxo's way is the shortest to-date in this thread if you want a Perl-only solution. But, since you are on Windows...
    perl -e "@file = (split/\n/,`dir /od /b /S`)[0..5]; print @file;"
    Which returns the top six oldest files in the current or any of its subdirectories.

    Celebrate Intellectual Diversity