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

Hello Monks,

I have one zip file, In that zip file there will be a txt file, I need to read the contents of the txt file without unzipping it.

Also In my server, Zip Module is not installed i guess(based on the below error description). I am not authorized to install the zip package.

Can't locate Archive/Zip.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .)

Is there any way to read contents inside the zip file without unzipping and without Zip.pm installed ?

Thank you very much in Advance

Regards,

Sekhar

  • Comment on Without Unzipping and without using Archive module Can we read the file in zip file

Replies are listed 'Best First'.
Re: Without Unzipping and without using Archive module Can we read the file in zip file
by haukex (Archbishop) on Mar 01, 2018 at 07:28 UTC

    As VinsWorldcom already said, Yes, even you can use CPAN.

    But luckily, IO::Uncompress::Unzip is a core module:

    use warnings; use strict; use IO::Uncompress::Unzip (); my $filename = 'foo.zip'; my $membername = 'bar.txt'; my $z = IO::Uncompress::Unzip->new($filename, Name=>$membername) or die "unzip failed: $IO::Uncompress::Unzip::UnzipError\n"; while (my $line = <$z>) { # do something with each $line } $z->close;
      A key thing to point out about that module is that it is unzipping and providing the data from the archive on the fly. So, if what you mean by "without unzipping it" is that you don't want to spend the time or the disk-space decompressing the entire archive, this core module probably does satisfy your requirement. (The perldoc clearly shows how the file-glob reference is equivalent to "getline().")
Re: Without Unzipping and without using Archive module Can we read the file in zip file
by davido (Cardinal) on Mar 01, 2018 at 02:53 UTC

    This is far more fragile than using a real module, but takes advantage of the unzip utility which may be installed on your system. If it is not, then you're going to need to either install a module, install an unzip utility that can list the contents of zipfiles, or implement your own version of unzip that will read the contents of a zipfile.

    #!/usr/bin/env perl use strict; use warnings; my $filename = '/home/someuser/foo.zip'; my $read = `unzip -l $filename`; # Read in the output of the unzip -l +command. chomp(my @contents = split /\n/, $read); # Note: # $contents[0] contains the archive name. # $contents[1] contains the header. # $contents[2] contains a header delimiter ------. # $contents[3] contains the first file listing. # ..... # $contents[-3] contains last file listing. # $contents[-2] contains a footer delimiter ------. # $contents[-1] contains a summary. + my $pos = index $contents[1], 'Name'; # Find the 'Name' +field. The start of that field is # the position in +subsequent lines where filenames # begin. + + my $n = 1; # Keep track of row number, just because. + + foreach my $item (@contents[3 .. $#contents - 2]) { # Start with the f +irst file entry, and end with the last file entry. my $filename = substr($item, $pos); # Use our index po +sition to look for a substring starting where # the Name field b +egan. print $n++, ": $filename\n"; # Print out output +. }

    One might ask why I used index and substr instead of a regular expression. The main reason is that it seemed easier to base the location of filenames on the column of the header for filenames rather than trying to concoct a regular expression that would find the filenames without being fooled by whitespace or entities that look like other fields in the original output. It's also hard to know whether the assumption about what line number in the output is where filenames begin is a good assumption or not. It works for my system, and probably most other GNU/Linux systems, but YMMV.

    The output of unzip -l on my system resembles this:

    Archive: /home/davido/Downloads/dash-to-dock@micxgx.gmail.com.v61.she +ll-extension.zip Length Date Time Name --------- ---------- ----- ---- 0 2017-09-06 14:09 locale/zh_CN/LC_MESSAGES/ 2754 2017-09-06 14:09 stylesheet.css 8981 2017-09-06 14:09 locale/es/LC_MESSAGES/dashtodock.mo ...(and so on...) 635 2017-12-23 17:29 metadata.json --------- ------- 659482 82 files

    So by looking at this hopefully it's easier to see why I skip the first three lines, and the last two, and why it felt easier to grab the filenames starting at the column where the Name header begins.

    But really, the right thing to do is to use a module that deals correctly with the nuances solutions like this one fail to consider, and that has benefitted from the refining process of bugfixes resulting from issues raised by the CPAN user community.


    Dave

Re: Without Unzipping and without using Archive module Can we read the file in zip file
by VinsWorldcom (Prior) on Mar 01, 2018 at 00:40 UTC

    You can install the needed module(s) - see Yes, even you can use CPAN or local::lib.

    As for viewing contents without unzipping, I'm still unclear based on your wording:

    • Do you want to get a listing of the ZIP file contents?
    • Do you want to see the contents of each file inside the ZIP file?
      Thank you very much, It's working now :)
Re: Without Unzipping and without using Archive module Can we read the file in zip file
by Miguel (Friar) on Mar 01, 2018 at 14:05 UTC
    Is there any way to read contents inside the zip file without unzipping and without Zip.pm installed ?
    Another way (edit: to read one file inside a zip file):
    #!/usr/bin/env perl use strict; use warnings; use utf8; my $zip_file = q|test.zip|; my $cmd = q|/usr/bin/zless|; my $content = qx|$cmd $zip_file|; print $content;
      Thank you Miguel, I have used your code snippet, Its working. Thank you so much