Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Getting IO::Compress::Zip to include directory entries (on Windows)

by hilitai (Monk)
on Feb 02, 2016 at 22:16 UTC ( [id://1154303]=perlquestion: print w/replies, xml ) Need Help??

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

My task is: take a zip file (really a .war file, but I assume that's neither here nor there), uncompress it into a directory structure, manipulate a few files, and rezip it into a new zip file.

I think I'm about 99% there. I've got a small script that uses IO::Uncompress::Unzip and IO::Compress::Zip to extract the files and then recompress them. However, when I do the recompression, I can't get the zip method of IO::Compress::Zip to include directory entities, as the original war file did. For example, the original file contains an entry for the directory WEB-INF/. My output file contains entries for all the files within WEB-INF/, but nothing for the directory itself.

Here's some sample code. Assume two files, tc.html and tc.html.gz, and a directory, WEB-INF. The following code will compress the two files into a zip:

#!/usr/bin/perl use strict; use warnings; use IO::Compress::Zip qw(:all); my $outfile = "test.zip"; my @dirs = ("tc.html", "tc.html.gz"); zip \@dirs => "$outfile", BinModeIn => 0 or die "$!"; print "Done\n";

But I can find no variant of that zip invocation that will include the directory without dying, e.g.:

my @dirs = ("tc.html", "tc.html.gz", "WEB-INF");

Running with this modification gets me:

Died at C:\Temp\zipSnip.pl line 10.

Am I missing some option? Or am I stuck?

Note that I am using IO::Compress and IO::Uncompress because I am trying to use *only* core modules. I don't think Archive::Zip counts.

Replies are listed 'Best First'.
Re: Getting IO::Compress::Zip to include directory entries (on Windows)
by dasgar (Priest) on Feb 02, 2016 at 23:13 UTC

    Looking the FilterName option portion of the documentation for IO::Compress::Zip, I was able to figure out a syntax that appeared to work for me.

    I created a directory named 'test_dir' and created two text files in that directory. Then I used the following code:

    use strict; use warnings; use IO::Compress::Zip qw(:all); my $outfile = "test.zip"; my $dir = "test_dir"; zip [ <$dir/*.txt> ] => $outfile, BinModeIn => 0 or die "zip failed: +$ZipError\n";

    When I ran the code, it created a zip file that had a directory named 'test_dir', which in turn contained the two text files. This was done on Windows 7 using Strawberry Perl 5.20.0 and IO::Compress::Zip 2.064.

    Hopefully the code above will help point you in the right direction for what you're trying to do.

      Thanks! But I guess I wasn't clear enough. I can already include all the files, in whatever directory; what I'm trying to do is include the directory entry itself, like a native zip program would do.

      For example, here's the output of Zip 3.0:

      C:\Temp\ztest>zip -r test2.zip WEB-INF adding: WEB-INF/ (208 bytes security) (stored 0%) <-- dir, not file adding: WEB-INF/deploy/ (208 bytes security) (stored 0%) <-- ditto adding: WEB-INF/deploy/client/ (208 bytes security) (stored 0%) adding: WEB-INF/deploy/client/rpcPolicy/ (208 bytes security) (store +d 0%) adding: WEB-INF/deploy/client/rpcPolicy/manifest.txt (208 bytes secu +rity) (deflated 4%) <-- first actual file

      So it's stored the directory entities and information (including modification times) as well as the files. That's what I'm trying to emulate.

      I've done some more digging around, and I'm beginning to think that IO::Compress::Zip might just not do what I want. Also, I didn't think that Archive::Zip was in the core libraries, but it looks like it has been since v 5.12 or so, maybe. (On the other hand, I have to work with some very old systems.)

      I might not even need this ability for what I want to do, but the closer I can come to a Real Zip File on output, the better.

        what I'm trying to do is include the directory entry itself

        In the docs it says filenames only

        If $input is an array reference, each element in the array must be a filename. The input data will be read from each file in turn. The complete array will be walked to ensure that it only contains valid filenames before any data is compressed.
        poj
        But I guess I wasn't clear enough.

        Actually, I think that I understood you correctly, but I probably failed to properly describe what I tested.

        Here's the file and directory layout of what I tested (and the contents of test.pl is the code from my previous post):

        C:\test\test.pl C:\test\test_dir\file1.txt C:\test\test_dir\file2.txt

        After running perl test.pl, I got a new file: C:\test\test.zip. Here's the contents of test.zip:

        test_dir\file1.txt test_dir\file2.txt

        As you can see, the file and directory structure was fully and correctly added into the new zip file. And a quick check shows that the two text files' modification date/time stamp is preserved in the new zip file too. I believe that is the basic idea of what you are trying to do. However, I suspect that you'll need to make modifications to the code that I posted in order to fully do what you're trying to do.

Re: Getting IO::Compress::Zip to include directory entries (on Windows)
by Mr. Muskrat (Canon) on Feb 03, 2016 at 00:45 UTC

    Have you tried using one of the generated files? If not, you might be wasting time trying to find a solution for a non-existent problem.

      ...and it turns out that the files created by IO::Compress::Zip appear to work just fine, and thus my concerns are groundless. Thanks for the replies, though.

Re: Getting IO::Compress::Zip to include directory entries (on Windows)
by Anonymous Monk on Feb 03, 2016 at 17:56 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1154303]
Approved by Mr. Muskrat
Front-paged by stevieb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (8)
As of 2024-04-24 10:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found