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

Hi. I'm writing a routine, part of which should examine a particular folder, look for .htm, .doc, or .pdf files older than 3 days old, and prompt the user to delete them if it finds any. If it doesn't find any, the user should get no prompt at all, and the rest of the routine should run.

Right now the code I have prompts the user each and every time it finds a file older than 3 days. Not quite what I want. Also, the final print command ('No files deleted...') is just there for testing purposes at this point.

Here's the code:

my @htm_files = glob "C:/input/*.htm"; my @doc_files = glob "C:/input/*.doc"; my @pdf_files = glob "C:/input/*.pdf"; my @bigarray = (@htm_files, @doc_files, @pdf_files); foreach my $file (@bigarray) { if (-M $file > 3) { print "Delete files older than 3 days? [Y or N] \n"; chomp ($cleanup = <STDIN>); if ($cleanup =~ /Y/i) { unlink $file; } else { print "\n <<No files deleted at this time>>\n"; } } }

Replies are listed 'Best First'.
Re: one user prompt instead of many
by Aristotle (Chancellor) on Jan 26, 2005 at 17:41 UTC

    You need to accumulate the list first, then ask the user in case there are any entries, and delete them if so.

    my @everyfile = ( glob( "C:/input/*.htm" ), glob( "C:/input/*.doc" ), glob( "C:/input/*.pdf" ), ); my @oldfile = grep -M > 3, @everyfile; if( @oldfile ) { print "Delete files older than 3 days? [Y or N] \n"; chomp( $cleanup = <STDIN> ); if( $cleanup =~ /Y/i ) { unlink @oldfile; } else { print "\n <<No files deleted at this time>>\n"; } }

    Note that you can pass multiple files to unlink. Don't loop.

    Makeshifts last the longest.

Re: one user prompt instead of many
by davido (Cardinal) on Jan 26, 2005 at 17:43 UTC

    Remove the prompting from inside the loop. Then do this: Each time a file is found that has a "last modified" time of greater than three days, push $file into @found. At the end of the loop, if @found contains entries, then prompt the user if he wants them deleted. If the response is yes, then "unlink @found;".


    Dave

Re: one user prompt instead of many
by bibliophile (Prior) on Jan 26, 2005 at 17:43 UTC
    Maybe move the question outside the loop?
    print "Delete files older than 3 days? [Y or N] \n"; chomp ($cleanup = <STDIN>); if ($cleanup =~ /Y/i) { foreach my $file (@bigarray) { ... } }

    Untested!

    Update:
    Wow, you guys are *fast*! Two responses as I was typing my (meagre) thought....

Re: one user prompt instead of many
by Tanktalus (Canon) on Jan 26, 2005 at 18:26 UTC

    Hmmm ... I wonder if glob can handle {}'s ... glob "C:/input/*.{htm,doc,pdf}". Not really that important, I suppose.

    You probably want to grep here...

    my @htm_files = glob "C:/input/*.htm"; my @doc_files = glob "C:/input/*.doc"; my @pdf_files = glob "C:/input/*.pdf"; # only keep the files more than 3 days old. my @oldfiles = grep { -M $file > 3 } (@htm_files, @doc_files, @pdf_fil +es); # if we have any such files... if (@oldfiles) { print "Delete files older than 3 days? [Y or N] \n"; chomp ($cleanup = <STDIN>); if ($cleanup =~ /Y/i) { unlink foreach @oldfiles; } else { print "\n <<No files deleted at this time>>\n"; } } else { print "\n No files to delete\n"; }