I needed to work the zip files and process the text files within it. My zipped filed contained *.out files. Thanks to technique mentioned by castaway. This doesn't make any use of modules like Archieve::Zip.
foreach $zip_file (@zip_files){ open ZIPS, "unzip -l $zip_file|"; while(<ZIPS>){ push @text_files,$1 if /(\d+.out)$/; } foreach $text_file (@text_files){ open IN, "unzip -p $zip_file $text_file|"; my (@required_data) = process_file(\*IN); } }

Replies are listed 'Best First'.
Re: Reading the Zipped Files.
by Anonymous Monk on Jun 03, 2003 at 22:31 UTC
    This doesn't make any use of modules like Archieve::Zip

    But does require the presence of an unzip binary in the current path which accepts those arguments used in your snippet - This doesn't make your code any more portable when compared to the usage of Archive::Zip, but does introduce some serious security concerns, such as if malicious commands were passed into the @zip_files array.

    Thanks anyway, but I'd rather use Archive::Zip ...

    use Archive::Zip qw/ :ERROR_CODES /; my $zip = Archive::Zip->new; my $status = $zip->read( $file ); if ( $status != AZ_OK ) { die "Error in reading zip file -- Return status ", $status; } foreach my $member ( $zip->members ) { next unless $member->fileName =~ /\.out$/; $zip->extractMember( $member ); }
Re: Reading the Zipped Files.
by Anonymous Monk on Jun 03, 2003 at 22:26 UTC
    unzip -l archive.zip *.out | perl -ne 'if (/(\S+\.out)$/){ print $1," +", `unzip -p archive.zip $1`, $/}'
      This won't work as the *.out will be expanded by the shell and attempt to match out files within the current directory in the zip file. This is the way by which I would do this ...

      unzip -l archive.zip | grep \.out$ | awk '{ print $4 }' | xargs unzip +archive.zip

      Note however, I would not call this portable because it is dependent upon the output of the unzip binary to place the file name of archive members as the fourth element on the line (which is at least what unzip on our Solaris development box does). A more portable overall method would be to use Archive::Zip such as suggested by the ever venerable Anonymous Monk here rather than depending upon the output of external binaries.

       

      perl -le 'print+unpack"N",pack"B32","00000000000000000000001001100101"'

        Useless use of grep (besides the fact it's not even necessary as you can quote the glob and pass it to unzip):
        awk '/\.out$/ { print $4 }'

        Makeshifts last the longest.

        The shell will expand the star only if there are *.out files in the current directory. However, quoting the pattern, the snippet works as advertized.

        unzip -l archive.zip "*.out" | perl -ne 'if (/(\S+\.out)$/){ print $1, +" ", `unzip -p archive.zip $1`, $/}'

        The purpose of this snippet was to emphasize that artist is doing something unnecessarily complicated. Since his method is not portable, at least he should try not to waste resources. ;)

Re: Reading the Zipped Files.
by Aristotle (Chancellor) on Jun 04, 2003 at 00:17 UTC

    Something went wrong there. You're looping over a list of @zip_files, but never record which one a given $text_file[$N] belongs to. Then you attempt to extract all text files from a single zip? That won't fly.

    Makeshifts last the longest.

      If you see carefully the internal foreach loop contains $zip_file which comes from the external foreach loop.

      artist

        Hi. If you see carefully the internal foreach loop contains $zip_file which comes from the external foreach loop.

        'twould be a lot easier for him to see if you would indent your code properly, e.g.,

        foreach $zip_file (@zip_files){ open ZIPS, "unzip -l $zip_file|"; while(<ZIPS>){ push @text_files,$1 if /(\d+.out)$/; } foreach $text_file (@text_files){ open IN, "unzip -p $zip_file $text_file|"; my (@required_data) = process_file(\*IN); } }
        Then you can actually see what's internal or external to what.

        BTW, I really have to wonder what the purpose of posting this is. It's too specific to serve a general purpose and too general to serve a specific purpose. There are thousands of people with thousands of snippets they could post, but we'd be in trouble if they all did (you might want to google "categorical imperative" for a more general philosophical treatment of this problem). I'd stick with things that might be helpful to a large number of people and that are in some way novel.

        Edit by tye, replace PRE with BLOCKQUOTE