I am trying to extract a ZIP file in Perl. In my script, i can detect a ZIP file, i can select this .zip but after ?
elsif ( $$file{'ccname'} =~ /(\.zip)$/x )
{
# Extraction ZIP
my $zip_path=
Could you help me ?
Regards,
I am trying to extract a ZIP file in Perl. In my script, i can detect a ZIP file, i can select this .zip but after ?
elsif ( $$file{'ccname'} =~ /(\.zip)$/x )
{
# Extraction ZIP
my $zip_path=
Could you help me ?
Regards,
The tool for this job is the Archive::Zip
module.
my $somezip = Archive::Zip->new();
unless ( $somezip->read( 'someZip.zip' ) == AZ_OK ) {
die 'read error';
}
and
my @members = $zip->members();
Here is an example :
use strict;
use warnings;
use Archive::Extract;
my $extractor = Archive::Extract->new( archive => 'yourZippedfileName.zip' );
$extractor.extract; #extract the files to the current working directory
I've actually just did this for a program I wrote. I used IO::Uncompress::Unzip
which is a standard module in Perl. This took me a while to piece together. The explanation for IO::Uncompress::Unzip
isn't the greatest, and it took a bit of trial and error.
These are the main points:
IO::Uncompress::Unzip
. If the status is less than zero, you have a problem. In that case, just die
.nextStream
. From here, you can get the Name
of the stream which will be your file and directory name.Name
is foo/bar/barfu/foobar.txt
, you need to make sure foo/bar/barfu
exists, so you can write out foobar.txt
while
loop to read from the stream's buffer and write to the file itself. This has to be a loop because it might take several attempts before you've read the whole stream. This is what took me a while to realize.IO::File
which isn't necessary. I did this because everything else in this program was Object Oriented, and I figured it was time to try out the OO interface for file reading and writing. It adds nothing but confusion. Use open
and print
or say
directly as you would in standard Perl.File::Spec
to join together the directories and file names. It's officially the correct way to join together file and directory names. After all, you don't know if you have to run your program on a Vax or a Mac Plus running System 7. If you know you're only running on Windows, Linux, Unix, or Mac OS X, you can get away with $directory/$file
instead of File::Spec->join($directory, $file)
. Just don't blame me if your boss is upset that your script can't run on his PDP-11.Here's an excerpt from my program:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use File::Basename qw(basename dirname);
use File::Path qw(make_path remove_tree);
use File::Spec;
use File::Temp qw(tempfile tempdir);
use IO::File;
use IO::Uncompress::Unzip;
sub update_zip {
my $old_zip_file = shift;
my $old_version = shift;
my $new_version = shift;
my $zip_directory_name = dirname $old_zip_file;
my $zip_file_name = basename $old_zip_file;
my $unzip_directory = tempdir(
"$old_zip_file.XXXX",
DIR => $zip_directory_name,
);
#
# Unzip Artifact
#
my $zip_fh = IO::Uncompress::Unzip->new( $old_zip_file )
or die qq(Cannot open zip "$old_zip_file" for reading.);
#
# Go through each element in Zip file
#
while ( my $status = $zip_fh->nextStream ) {
if ( $status < 0 ) {
die qq(Error in Zip: $IO::Uncompress::Unzip::UnzipError.);
}
my $element_name = $zip_fh->getHeaderInfo->{Name};
next if $element_name =~ m{/$}; # Skip Directories
my $element_dir = dirname $element_name;
my $full_element_dir = File::Spec->join( $unzip_directory, $element_dir );
my $full_element_name = File::Spec->join( $unzip_directory, $element_name );
if ( not -d $full_element_dir ) {
make_path $full_element_dir
or die qq(Can't make directory "$full_element_dir".);
}
my $unzipped_fh = IO::File->new( $full_element_name, "w" )
or die qq(Can't open file "$full_element_name" for writing: $!);
my $buffer;
while ( my $status = $zip_fh->read( $buffer ) ) {
if ( $status < 0 ) {
die qq(Error in Zip: $IO::Uncompress::Unzip::UnzipError.);
}
$unzipped_fh->write( $buffer );
}
$unzipped_fh->close;
}
$zip_fh->close;
}