Great answer. Thank you (and thank you to all who added their two cents). I solved this by using two loops. One to create the file list and the second to go through the list and issue the system commands for each item.
sub gzip {
my $cmd = shift;
my $dir = shift;
my ($file, $fullfile);
my @files = ();
print "$cmd files in $dir...\n";
# Make sure command is secure and predictable.
if ( $cmd eq 'zip' ){
$cmd = 'gzip';
} elsif ( $cmd eq 'unzip' ){
$cmd = 'gunzip';
} else {
warn "zip or unzip command not given $!";
}
# Generate list of files
opendir DIR, $dir or warn "Cannot open $dir $!";
while ( defined ( $file = readdir(DIR) ) ){
$fullfile = "$dir/$file";
next if ( !-f $fullfile
|| $file =~ m/\.txt$/
|| $file !~ m/^[\w-]+(\.[\w-]+)*$/ );
push @files, $fullfile;
}
closedir DIR;
# Using file list from above, issue zip or unzip command. You can
+not do
# both in the same loop as the readdir may pickup the newly create
+d files
# and try to process them. Thus you may endup to zipping a zipped
+ file or
# unzipping an upzipped file.
while (<@files>) {
system ( "$cmd $_") == 0 or warn "Cannot $cmd $fullfile : $!";
}
}