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

Hello Monks! I have written a program to compare the file counts between two folders and once matched the files in the second folder are zipped and the ones in the first folder are deleted. My program functions as expected except for the deleting of files in the second folder. Could you please help. This is what I have so far

#!/usr/local/bin/perl use strict; use warnings; use Archive::Zip qw( :ERROR_CODES ); my $directory1 = 'C:\Perl\test'; chdir($directory1) or die "Can't chdir to $directory1 $!"; opendir(DIR1, $directory1) || die "Couldn't opendir: $!\n"; my @files = grep { $_ ne '.' && $_ ne '..' } readdir DIR1; my $a =0 ; foreach(@files){ $a++; } my $directory = 'C:\Perl\compress'; chdir($directory) or die "Can't chdir to $directory $!"; opendir(DIR, $directory) || die "Couldn't opendir: $!\n"; my @files2 = grep { $_ ne '.' && $_ ne '..' } readdir DIR; my $b=0; my $c=0; foreach(@files2){ $b++; } # while loop to try every min for 3 mins if any the file counts a & b +don't match while($c < 3) { if ($a eq $b) { compress(\@files2); unlink @files2; #delete files in the compress folder after + compression is complete unlink @files; #delete files in the test folder; $c=3; } else { print "Count Compare Failed!\n"; sleep 60; @files2 = grep { $_ ne '.' && $_ ne '..' } readdir DIR; $b=0; } $c++; foreach(@files2){ $b++; } } # subroutine to compress the files into one sub compress { my @add_array=@{ $_[0] }; my $obj = Archive::Zip->new(); # new instance foreach (@add_array) { $obj->addFile($_); # add files } if ($obj->writeToFileNamed('testing.zip') != AZ_OK) { # write to di +sk print "Error in archive creation!"; } else { print "Archive created successfully!"; } } closedir(DIR1); closedir(DIR);

Replies are listed 'Best First'.
Re: Deleting files in the first folder
by toolic (Bishop) on May 09, 2011 at 23:15 UTC
Re: Deleting files in the first folder
by GrandFather (Saint) on May 10, 2011 at 03:56 UTC

    Most likely your problem is that you try to reread using DIR without reopening it. However there are a number of things that will help to tidy your code up. Consider (untested):

    #!/usr/local/bin/perl use strict; use warnings; use Archive::Zip qw( :ERROR_CODES ); my @testFiles = listFiles ('C:\Perl\test'); # while loop to try every min for 3 mins if any the file counts a & b +don't match my $retries = 0; while ($retries++ < 3) { my @compressFiles = listFiles ('C:\Perl\compress'); if (@testFiles == @compressFiles) { compress (\@compressFiles); unlink @compressFiles; #delete compressed files unlink @testFiles; #delete test files last; } print "Count Compare Failed!\n"; sleep 60; } sub listFiles { my ($dirName) = @_; chdir ($dirName) or die "Can't chdir to $dirName: $!"; opendir my ($scan), $dirName or die "Couldn't opendir $dirName: $! +\n"; return grep {$_ ne '.' && $_ ne '..'} readdir $scan; } sub compress { my @add_array = @{$_[0]}; my $obj = Archive::Zip->new (); # new instance $obj->addFile ($_) foreach @add_array; # add files if ($obj->writeToFileNamed ('testing.zip') != AZ_OK) { # write +to disk print "Error in archive creation!"; } else { print "Archive created successfully!"; } }

    Note in particular that an array in scalar context provides the number of elements in the array so the test file count is simply @testFiles for example.

    If you find yourself repeating more than a couple of lines of code consider using a sub instead. In this case listFiles not only makes the code more compact, but clears the flow up so it's easier to see where the error was.

    Note that this code does not compare files, but only the number of file and directory entries in the subject folders. In particular, if files change names, but the number of files don't this code (probably) will not do what you want!

    True laziness is hard work
      GrandFather, your code is doing the same as my code. It does not delete the files from the test folder. Thanks for cleaning up the code! could you please help with the deletion of files in the test folder. Owais

        Heh! That's where the "untested" bit comes in, and without testing I suspect the fix is to change the two unlink lines:

        unlink map {"C:\\Perl\\compress\\$_"} @compressFiles; #delete +compressed files unlink map {"C:\\Perl\\test\\$_"} @testFiles; #delete +test files

        readdir doesn't generate full paths so unless the current directory happens to be the directory containing the files to be deleted, the unlink will fail. The map generates the full path to each file to be deleted.

        True laziness is hard work
Re: Deleting files in the first folder
by Anonymous Monk on May 10, 2011 at 02:06 UTC
    #!/usr/bin/perl -- use strict; use warnings; use File::Spec; use File::Temp qw' tempdir '; use Shell::Command qw' touch '; Main( @ARGV ); exit( 0 ); sub Main { my $dir = tempdir( CLEANUP => 1 ); chdir $dir or die "Can't chdir('$dir'): $!"; touch(1,2); Dunlink(1,2,3); chdir File::Spec->updir(); # for CLEANUP to work } sub Dunlink { use Carp qw' carp '; for my $file ( @_ ){ unlink $file or carp "Can't unlink('$file'): $!"; } } __END__ Can't unlink('3'): No such file or directory at - line 21 main::Dunlink(1, 2, 3) called at - line 14 main::Main() called at - line 7