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

Hello, I'm new to perl and trying to unzip files with Archive::Zip qw( :ERROR_CODES :CONSTANTS )

It's working great but when I try to print the zip members they appear twice.

In fact they are already counted twice with my @members = $zip->members() and it's the same with $zip->memberNames

Any idea why? And how can I print the zip members only once or counting them correctly?

#Subroutine to Unzip Files (XXX.zip => ./XXX/) sub unzip_files_to_dir{ $logger->info("======================= START UNZIP ================= +======"); foreach (@list_FTP) { $logger->info("Trying to Unzip : $_"); #initialising zip file my $zip = Archive::Zip->new($_); if ($zip->read($_) == AZ_OK){ my $new_folder = basename($_, ".zip"); $logger->info("Creating new_folder : $new_folder"); mkpath($new_folder); #my @names = $zip->memberNames; $logger->info("Zip content :"); #print "\t".$_, "\n" for @names; # Loop through the members, printing their name, # compressed size, and uncompressed size. my @members = $zip->members(); my $nbr_members = @members; print "Number of files in zip : $nbr_members "; # print 4 when t +here are only 2 files?? foreach (@members){ print " - " . $_->fileName() . ": " . $_->compressedSize() . " (" . $_->uncompressedSize() . ")\n"; } $zip->extractTree("",$dirIN.$new_folder); } } }

I worked around that by dividing the nbr of members by 2 and breaking the foreach loop when they are printed once. But that's really ugly and sad :'(

Replies are listed 'Best First'.
Re: Archive::Zip members print twice
by Athanasius (Archbishop) on Mar 03, 2016 at 12:40 UTC

    Hello Coroner, and welcome to the Monastery!

    Within the loop foreach (@list_FTP), the statement:

    my $zip = Archive::Zip->new($_);

    creates a new Archive::Zip object and initialises it with the contents of the zip file named by $_. The object now contains one member. Then, in the conditional:

    if ($zip->read($_) == AZ_OK)

    the contents of that same zip file are again added to the archive object, which now contains two members!

    One solution is to create an empty object and populate it only via the read method:

    for (@list_FTP) { $logger->info("Trying to Unzip : $_"); #initialising zip file my $zip = Archive::Zip->new(); # <-- create empty archive if ($zip->read($_) == AZ_OK) { ...

    BTW, it’s better practice to pass a variable such as @list_FTP as an argument to the subroutine.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thanks Athanasius for the reply. Works Great! I get it now ;)

      Thanks for the best practice advice too :)