File Coverage

bin/streamzip
Criterion Covered Total %
statement 46 53 86.7
branch 11 20 55.0
condition 3 3 100.0
subroutine 15 18 83.3
pod n/a
total 75 94 79.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             # Streaming zip
4              
5 28     28   167032 use strict;
  28         49  
  28         1132  
6 28     28   128 use warnings;
  28         40  
  28         12561  
7              
8 28         4958 use IO::Compress::Zip qw(zip
9             ZIP_CM_STORE
10             ZIP_CM_DEFLATE
11 28     28   21717 ZIP_CM_BZIP2 ) ;
  28         2260  
12              
13 28     28   22961 use Getopt::Long;
  28         515180  
  28         258  
14              
15 28         5842721 my $VERSION = '1.00';
16              
17 28         93 my $compression_method = ZIP_CM_DEFLATE;
18 28         72 my $stream = 0;
19 28         71 my $zipfile = '-';
20 28         78 my $memberName = '-' ;
21 28         103 my $zip64 = 0 ;
22 28         62 my $level ;
23              
24             GetOptions("zip64" => \$zip64,
25             "method=s" => \&lookupMethod,
26 2     2   17395 "0" => sub { $level = 0 },
27 2     2   3299 "1" => sub { $level = 1 },
28 2     2   3916 "2" => sub { $level = 2 },
29 2     2   3593 "3" => sub { $level = 3 },
30 2     2   4136 "4" => sub { $level = 4 },
31 2     2   2825 "5" => sub { $level = 5 },
32 2     2   4338 "6" => sub { $level = 6 },
33 2     2   3556 "7" => sub { $level = 7 },
34 2     2   4437 "8" => sub { $level = 8 },
35 2     2   3671 "9" => sub { $level = 9 },
36             "stream" => \$stream,
37             "zipfile=s" => \$zipfile,
38             "member-name=s" => \$memberName,
39 0     0   0 'version' => sub { print "$VERSION\n"; exit 0 },
  0         0  
40 28 50       1009 'help' => \&Usage,
41             )
42             or Usage();
43              
44 28 50       4843 Usage()
45             if @ARGV;
46              
47 28         79 my @extraOpts = ();
48              
49 28 100 100     230 if ($compression_method == ZIP_CM_DEFLATE && defined $level)
50             {
51 20         67 push @extraOpts, (Level => $level)
52             }
53              
54             # force streaming zip file when writing to stdout.
55 28 100       101 $stream = 1
56             if $zipfile eq '-';
57              
58 28 50       197 zip '-' => $zipfile,
59             Name => $memberName,
60             Zip64 => $zip64,
61             Method => $compression_method,
62             Stream => $stream,
63             @extraOpts
64             or die "Error creating zip file '$zipfile': $\n" ;
65              
66 28         0 exit 0;
67              
68             sub lookupMethod
69             {
70 6     6   11837 my $name = shift;
71 6         17 my $value = shift ;
72              
73 6         69 my %valid = ( store => ZIP_CM_STORE,
74             deflate => ZIP_CM_DEFLATE,
75             bzip2 => ZIP_CM_BZIP2,
76             lzma => 14,
77             xz => 95,
78             zstd => 93,
79             );
80              
81 6         25 my $method = $valid{ lc $value };
82              
83 6 50       28 Usage("Unknown method '$value'")
84             if ! defined $method;
85              
86 6 50       26 installModule("Lzma")
87             if $method == 14 ;
88              
89 6 50       23 installModule("Xz")
90             if $method == 95 ;
91              
92 6 50       19 installModule("Zstd")
93             if $method == 93;
94              
95 6         85 $compression_method = $method;
96             }
97              
98             sub installModule
99             {
100 0     0     my $name = shift ;
101              
102 0           eval " use IO::Compress::$name; use IO::Compress::Adapter::$name ; " ;
103 0 0         die "Method '$name' needs IO::Compress::$name\n"
104             if $@;
105             }
106              
107             sub Usage
108             {
109 0     0     print <<EOM;
110             Usage:
111             producer | streamzip [OPTIONS] | consumer
112             producer | streamzip [OPTIONS] -zipfile output.zip
113              
114             Stream data from stdin, compress into a Zip container, and either stream to stdout, or
115             write to a named file.
116              
117             OPTIONS
118              
119             -zipfile=F Write zip container to the filename 'F'
120             Outputs to stdout if zipfile not specified.
121             -member-name=M Set member name to 'M' [Default '-']
122             -0 ... -9 Set compression level for Deflate
123             [Default: 6]
124             -zip64 Create a Zip64-compliant zip file [Default: No]
125             Enable Zip64 if input is greater than 4Gig.
126             -stream Force a streamed zip file when 'zipfile' option is also enabled.
127             Only applies when 'zipfile' option is used. [Default: No]
128             Stream is always enabled when writing to stdout.
129             -method=M Compress using method 'M'.
130             Valid methods are
131             store Store without compression
132             deflate Use Deflate compression [Default]
133             bzip2 Use Bzip2 compression
134             lzma Use LZMA compression [needs IO::Compress::Lzma]
135             xz Use LZMA compression [needs IO::Compress::Xz]
136             zstd Use LZMA compression [needs IO::Compress::Zstd]
137             -version Display version number [$VERSION]
138              
139             Copyright (c) 2019-2026 Paul Marquess. All rights reserved.
140              
141             This program is free software; you can redistribute it and/or
142             modify it under the same terms as Perl itself.
143              
144             EOM
145 0           exit;
146             }
147              
148              
149             __END__
150             =head1 NAME
151              
152             streamzip - create a zip file from stdin
153              
154             =head1 SYNOPSIS
155              
156             producer | streamzip [opts] | consumer
157             producer | streamzip [opts] -zipfile=output.zip
158              
159             =head1 DESCRIPTION
160              
161             This program will read data from C<stdin>, compress it into a zip container
162             and, by default, write a I<streamed> zip file to C<stdout>. No temporary
163             files are created.
164              
165             The zip container written to C<stdout> is, by necessity, written in
166             streaming format. Most programs that read Zip files can cope with a
167             streamed zip file, but if interoperability is important, and your workflow
168             allows you to write the zip file directly to disk you can create a
169             non-streamed zip file using the C<zipfile> option.
170              
171             =head2 OPTIONS
172              
173             =over 5
174              
175             =item -zip64
176              
177             Create a Zip64-compliant zip container. Use this option if the input is
178             greater than 4Gig.
179              
180             Default is disabled.
181              
182             =item -zipfile=F
183              
184             Write zip container to the filename C<F>.
185              
186             Use the C<Stream> option to force the creation of a streamed zip file.
187              
188             =item -member-name=M
189              
190             This option is used to name the "file" in the zip container.
191              
192             Default is '-'.
193              
194             =item -stream
195              
196             Ignored when writing to C<stdout>.
197              
198             If the C<zipfile> option is specified, including this option will trigger
199             the creation of a streamed zip file.
200              
201             Default: Always enabled when writing to C<stdout>, otherwise disabled.
202              
203             =item -method=M
204              
205             Compress using method C<M>.
206              
207             Valid method names are
208              
209             * store Store without compression
210             * deflate Use Deflate compression [Default]
211             * bzip2 Use Bzip2 compression
212             * lzma Use LZMA compression
213             * xz Use xz compression
214             * zstd Use Zstandard compression
215              
216             Note that Lzma compress needs C<IO::Compress::Lzma> to be installed.
217              
218             Note that Zstd compress needs C<IO::Compress::Zstd> to be installed.
219              
220             Default is C<deflate>.
221              
222             =item -0, -1, -2, -3, -4, -5, -6, -7, -8, -9
223              
224             Sets the compression level for C<deflate>. Ignored for all other compression methods.
225              
226             C<-0> means no compression and C<-9> for maximum compression.
227              
228             Default is 6
229              
230             =item -version
231              
232             Display version number
233              
234             =item -help
235              
236             Display help
237              
238             =back
239              
240             =head2 Examples
241              
242             Create a zip file bt reading daa from stdin
243              
244             $ echo Lorem ipsum dolor sit | perl ./bin/streamzip >abcd.zip
245              
246             Check the contents of C<abcd,zip> with the standard C<unzip> utility
247              
248             Archive: abcd.zip
249             Length Date Time Name
250             --------- ---------- ----- ----
251             22 2021-01-08 19:45 -
252             --------- -------
253             22 1 file
254              
255             Notice how the C<Name> is set to C<->.
256             That is the default for a few zip utilities where the member name is not given.
257              
258             If you want to explicitly name the file, use the C<-member-name> option as follows
259              
260             $ echo Lorem ipsum dolor sit | perl ./bin/streamzip -member-name latin >abcd.zip
261              
262             $ unzip -l abcd.zip
263             Archive: abcd.zip
264             Length Date Time Name
265             --------- ---------- ----- ----
266             22 2021-01-08 19:47 latin
267             --------- -------
268             22 1 file
269              
270              
271             =head2 When to write a Streamed Zip File
272              
273             A Streamed Zip File is useful in situations where you cannot seek
274             backwards/forwards in the file.
275              
276             A good examples is when you are serving dynamic content from a Web Server
277             straight into a socket without needing to create a temporary zip file in
278             the filesystem.
279              
280             Similarly if your workflow uses a Linux pipelined commands.
281              
282             =head1 SUPPORT
283              
284             General feedback/questions/bug reports should be sent to
285             L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
286             L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
287              
288              
289             =head1 AUTHOR
290              
291             Paul Marquess F<pmqs@cpan.org>.
292              
293             =head1 COPYRIGHT
294              
295             Copyright (c) 2019-2026 Paul Marquess. All rights reserved.
296              
297             This program is free software; you can redistribute it and/or modify it
298             under the same terms as Perl itself.