#!/usr/bin/perl # Streaming zip use strict; use warnings; use IO::Compress::Zip qw(zip ZIP_CM_STORE ZIP_CM_DEFLATE ZIP_CM_BZIP2 ) ; use Getopt::Long; my $VERSION = '1.002'; my $compression_method = ZIP_CM_DEFLATE; my $stream = 0; my $zipfile = '-'; my $memberName = '-' ; my $zip64 = 0 ; my $level ; GetOptions("zip64" => \$zip64, "method=s" => \&lookupMethod, "0" => sub { $level = 0 }, "1" => sub { $level = 1 }, "2" => sub { $level = 2 }, "3" => sub { $level = 3 }, "4" => sub { $level = 4 }, "5" => sub { $level = 5 }, "6" => sub { $level = 6 }, "7" => sub { $level = 7 }, "8" => sub { $level = 8 }, "9" => sub { $level = 9 }, "stream" => \$stream, "zipfile=s" => \$zipfile, "member-name=s" => \$memberName, 'version' => sub { print "$VERSION\n"; exit 0 }, 'help' => \&Usage, ) or Usage(); Usage() if @ARGV; my @extraOpts = (); if ($compression_method == ZIP_CM_DEFLATE && defined $level) { push @extraOpts, (Level => $level) } zip '-' => $zipfile, Name => $memberName, Zip64 => $zip64, Method => $compression_method, Stream => $stream, @extraOpts or die "Error creating zip file '$zipfile': $\n" ; exit 0; sub lookupMethod { my $name = shift; my $value = shift ; my %valid = ( store => ZIP_CM_STORE, deflate => ZIP_CM_DEFLATE, bzip2 => ZIP_CM_BZIP2, lzma => 14, xz => 95, zstd => 93, ); my $method = $valid{ lc $value }; Usage("Unknown method '$value'") if ! defined $method; installModule("Lzma") if $method == 14 ; installModule("Xz") if $method == 95 ; installModule("Zstd") if $method == 93; $compression_method = $method; } sub installModule { my $name = shift ; eval " use IO::Compress::$name; use IO::Compress::Adapter::$name ; " ; die "Method '$name' needs IO::Compress::$name\n" if $@; } sub Usage { print <, compress it into a zip container and, by default, write a I zip file to C. No temporary files are created. The zip container written to C is, by necessity, written in streaming format. Most programs that read Zip files can cope with a streamed zip file, but if interoperability is important, and your workflow allows you to write the zip file directly to disk you can create a non-streamed zip file using the C option. =head2 OPTIONS =over 5 =item -zip64 Create a Zip64-compliant zip container. Use this option if the input is greater than 4Gig. Default is disabled. =item -zipfile=F Write zip container to the filename C. Use the C option to force the creation of a streamed zip file. =item -member-name=M This option is used to name the "file" in the zip container. Default is '-'. =item -stream Ignored when writing to C. If the C option is specified, including this option will trigger the creation of a streamed zip file. Default: Always enabled when writing to C, otherwise disabled. =item -method=M Compress using method C. Valid method names are * store Store without compression * deflate Use Deflate compression [Deflault] * bzip2 Use Bzip2 compression * lzma Use LZMA compression * xz Use xz compression * zstd Use Zstandard compression Note that Lzma compress needs C to be installed. Note that Zstd compress needs C to be installed. Default is C. =item -0, -1, -2, -3, -4, -5, -6, -7, -8, -9 Sets the compression level for C. Ignored for all other compression methods. C<-0> means no compression and C<-9> for maximum compression. Default is 6 =item -version Display version number =item -help Display help =back =head2 Examples Create a zip file bt reading daa from stdin $ echo Lorem ipsum dolor sit | perl ./bin/streamzip >abcd.zip Check the contents of C with the standard C utility Archive: abcd.zip Length Date Time Name --------- ---------- ----- ---- 22 2021-01-08 19:45 - --------- ------- 22 1 file Notice how the C is set to C<->. That is the default for a few zip utilities whwre the member name is not given. If you want to explicitly name the file, use the C<-member-name> option as follows $ echo Lorem ipsum dolor sit | perl ./bin/streamzip -member-name latin >abcd.zip $ unzip -l abcd.zip Archive: abcd.zip Length Date Time Name --------- ---------- ----- ---- 22 2021-01-08 19:47 latin --------- ------- 22 1 file =head2 When to write a Streamed Zip File A Streamed Zip File is useful in situations where you cannot seek backwards/forwards in the file. A good examples is when you are serving dynamic content from a Web Server straight into a socket without needing to create a temporary zip file in the filesystsm. Similarly if your workfow uses a Linux pipelined commands. =head1 SUPPORT General feedback/questions/bug reports should be sent to L (preferred) or L. =head1 AUTHOR Paul Marquess F. =head1 COPYRIGHT Copyright (c) 2019-2021 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.