Utility for reading and creating 'zip' archives.
This module archives and extracts files to and from a zip
archive. The zip format is specified by the "ZIP Appnote.txt" file,
available on the PKWARE web site
The zip module supports zip archive versions up to 6.1. However, password-protection and Zip64 are not supported.
By convention, the name of a zip file is to end with .zip
.
To abide to the convention, add .zip
to the filename.
-
To create zip archives, use function
zip/2
orzip/3
. They are also available ascreate/2,3
, to resemble theerl_tar
module. -
To extract files from a zip archive, use function
unzip/1
orunzip/2
. They are also available asextract/1,2
, to resemble theerl_tar
module. -
To fold a function over all files in a zip archive, use function
foldl/3
. -
To return a list of the files in a zip archive, use function
list_dir/1
orlist_dir/2
. They are also available astable/1,2
, to resemble theerl_tar
module. -
To print a list of files to the Erlang shell, use function
t/1
ortt/1
. -
Sometimes it is desirable to open a zip archive, and to unzip files from it file by file, without having to reopen the archive. This can be done by functions
zip_open/1,2
,zip_get/1,2
,zip_list_dir/1
, andzip_close/1
.
Limitations
-
Zip64 archives are not supported.
-
Password-protected and encrypted archives are not supported.
-
Only the DEFLATE (zlib-compression) and the STORE (uncompressed data) zip methods are supported.
-
The archive size is limited to 2 GB (32 bits).
-
Comments for individual files are not supported when creating zip archives. The zip archive comment for the whole zip archive is supported.
-
Changing a zip archive is not supported. To add or remove a file from an archive, the whole archive must be recreated.
Types
zip_comment() = #zip_comment{comment = string()}
The record zip_comment
only contains the archive comment for
a zip archive.
zip_file() =
#zip_file{name = string(),
info = file:file_info(),
comment = string(),
offset = integer() >= 0,
comp_size = integer() >= 0}
The record zip_file
contains the following fields:
name
The filename
info
File information as in
file:read_file_info/1
in Kernel
comment
The comment for the file in the zip archive
offset
The file offset in the zip archive (used internally)
comp_size
The size of the compressed file (the size of the uncompressed
file is found in info
)
filename() = file:filename()
The name of a zip file.
extension() = string()
extension_spec() =
all |
[extension()] |
{add, [extension()]} |
{del, [extension()]}
create_option() =
memory | cooked | verbose |
{comment, string()} |
{cwd, file:filename()} |
{compress, extension_spec()} |
{uncompress, extension_spec()}
These options are described in
create/3
.
handle()
As returned by
zip_open/2
.
Functions
foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason}
Fun = fun((FileInArchive, GetInfo, GetBin, AccIn) -> AccOut)
FileInArchive = file:name()
GetInfo = fun(() -> file:file_info())
GetBin = fun(() -> binary())
Acc0 = Acc1 = AccIn = AccOut = term()
Archive = file:name() | {file:name(), binary()}
Reason = term()
Calls
on
successive files in the Archive
, starting with
.
is the name that the file
has in the archive.
is a fun that returns information
about the file.
returns the file contents.
Both
and
must be called within the
. Their behavior is
undefined if they are called outside the context of
.
The
must return a new accumulator, which is
passed to the next call. foldl/3
returns the final accumulator
value.
is returned if the archive is
empty. It is not necessary to iterate over all files in the archive.
The iteration can be ended prematurely in a controlled manner
by throwing an exception.
Example:
>Name = "dummy.zip".
"dummy.zip" >{ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]).
{ok,{"dummy.zip", <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, 0,0,3,0,0,...>>}} >{ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).
{ok,[{"bar",<<"BAR">>, {file_info,3,regular,read_write, {{2010,3,1},{19,2,10}}, {{2010,3,1},{19,2,10}}, {{2010,3,1},{19,2,10}}, 54,1,0,0,0,0,0}}, {"foo",<<"FOO">>, {file_info,3,regular,read_write, {{2010,3,1},{19,2,10}}, {{2010,3,1},{19,2,10}}, {{2010,3,1},{19,2,10}}, 54,1,0,0,0,0,0}}]} >{ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).
{ok,{"dummy.zip", <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, 0,0,3,0,0,...>>}} >catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).
<<"FOO">>
list_dir(Archive) -> RetValue
Archive = file:name() | binary()
RetValue = {ok, CommentAndFiles} | {error, Reason :: term()}
CommentAndFiles = [zip_comment() | zip_file()]
list_dir(Archive, Options) -> RetValue
Archive = file:name() | binary()
RetValue = {ok, CommentAndFiles} | {error, Reason :: term()}
CommentAndFiles = [zip_comment() | zip_file()]
Options = [Option]
Option = cooked
table(Archive) -> RetValue
Archive = file:name() | binary()
RetValue = {ok, CommentAndFiles} | {error, Reason :: term()}
CommentAndFiles = [zip_comment() | zip_file()]
table(Archive, Options) -> RetValue
Archive = file:name() | binary()
RetValue = {ok, CommentAndFiles} | {error, Reason :: term()}
CommentAndFiles = [zip_comment() | zip_file()]
Options = [Option]
Option = cooked
list_dir/1
retrieves all filenames in the zip archive
.
list_dir/2
provides options.
table/1
and table/2
are provided as synonyms
to resemble the
erl_tar
module.
The result value is the tuple {ok, List}
, where List
contains the zip archive comment as the first element.
One option is available:
cooked
By default, this function opens the zip file in
raw
mode, which is faster but does not allow a remote
(Erlang) file server to be used. Adding cooked
to the
mode list overrides the default
and opens the zip file without option raw
.
t(Archive) -> ok
Archive = file:name() | binary() | ZipHandle
ZipHandle = handle()
Prints all filenames in the zip archive
to the Erlang shell. (Similar to tar t
.)
tt(Archive) -> ok
Archive = file:name() | binary() | ZipHandle
ZipHandle = handle()
Prints filenames and information about all files in the zip archive
to the Erlang shell.
(Similar to tar tv
.)
unzip(Archive) -> RetValue
Archive = file:name() | binary()
RetValue =
{ok, FileList} |
{ok, FileBinList} |
{error, Reason :: term()} |
{error, {Name :: file:name(), Reason :: term()}}FileList = [file:name()]
FileBinList = [{file:name(), binary()}]
unzip(Archive, Options) -> RetValue
Archive = file:name() | binary()
Options = [Option]
Option =
{file_list, FileList} |
cooked | keep_old_files | verbose | memory |
{file_filter, FileFilter} |
{cwd, CWD}FileList = [file:name()]
FileBinList = [{file:name(), binary()}]
FileFilter = fun((ZipFile) -> boolean())
CWD = file:filename()
ZipFile = zip_file()
RetValue =
{ok, FileList} |
{ok, FileBinList} |
{error, Reason :: term()} |
{error, {Name :: file:name(), Reason :: term()}}
extract(Archive) -> RetValue
Archive = file:name() | binary()
RetValue =
{ok, FileList} |
{ok, FileBinList} |
{error, Reason :: term()} |
{error, {Name :: file:name(), Reason :: term()}}FileList = [file:name()]
FileBinList = [{file:name(), binary()}]
extract(Archive, Options) -> RetValue
Archive = file:name() | binary()
Options = [Option]
Option =
{file_list, FileList} |
keep_old_files | verbose | memory |
{file_filter, FileFilter} |
{cwd, CWD}FileList = [file:name()]
FileBinList = [{file:name(), binary()}]
FileFilter = fun((ZipFile) -> boolean())
CWD = file:filename()
ZipFile = zip_file()
RetValue =
{ok, FileList} |
{ok, FileBinList} |
{error, Reason :: term()} |
{error, {Name :: file:name(), Reason :: term()}}
unzip/1
extracts all files from a zip archive.
unzip/2
provides options to extract some files, and more.
extract/1
and extract/2
are provided as synonyms
to resemble module
erl_tar
.
If argument
is specified as a binary,
the contents of the binary is assumed to be a zip archive,
otherwise a filename.
Options:
{file_list, FileList }
By default, all files are extracted from the zip
archive. With option {file_list,
,
function unzip/2
only extracts the files
whose names are included in
. The full
paths, including the names of all subdirectories within
the zip archive, must be specified.
cooked
By default, this function opens the
zip file in raw
mode, which is faster but does not allow
a remote (Erlang) file server to be used. Adding cooked
to the mode list overrides the default and opens the zip file
without option raw
. The same applies for the files
extracted.
keep_old_files
By default, all files with the same name as files in
the zip archive are overwritten. With option keep_old_files
set, function unzip/2
does not overwrite existing files.
Notice that
even with option memory
specified, which
means that no files are overwritten, existing files are
excluded from the result.
verbose
Prints an informational message for each extracted file.
memory
Instead of extracting to the current directory,
the result is given as a list of tuples
{Filename, Binary}
, where Binary
is a binary
containing the extracted data of file Filename
in the zip archive.
{cwd, CWD}
Uses the specified directory as current directory. It is
prepended to filenames when extracting them from the
zip archive. (Acting like
file:set_cwd/1
in Kernel,
but without changing the global cwd
property.)
zip(Name, FileList) -> RetValue
Name = file:name()
FileList = [FileSpec]
FileSpec =
file:name() |
{file:name(), binary()} |
{file:name(), binary(), file:file_info()}RetValue =
{ok, FileName :: file:name()} |
{ok, {FileName :: file:name(), binary()}} |
{error, Reason :: term()}
zip(Name, FileList, Options) -> RetValue
Name = file:name()
FileList = [FileSpec]
FileSpec =
file:name() |
{file:name(), binary()} |
{file:name(), binary(), file:file_info()}Options = [Option]
Option =
memory | cooked | verbose |
{comment, Comment} |
{cwd, CWD} |
{compress, What} |
{uncompress, What}What =
all | [Extension] | {add, [Extension]} | {del, [Extension]}Extension = Comment = string()
CWD = file:filename()
RetValue =
{ok, FileName :: file:name()} |
{ok, {FileName :: file:name(), binary()}} |
{error, Reason :: term()}
create(Name, FileList) -> RetValue
Name = file:name()
FileList = [FileSpec]
FileSpec =
file:name() |
{file:name(), binary()} |
{file:name(), binary(), file:file_info()}RetValue =
{ok, FileName :: filename()} |
{ok, {FileName :: filename(), binary()}} |
{error, Reason :: term()}
create(Name, FileList, Options) -> RetValue
Name = file:name()
FileList = [FileSpec]
FileSpec =
file:name() |
{file:name(), binary()} |
{file:name(), binary(), file:file_info()}Options = [Option]
Option = create_option()
RetValue =
{ok, FileName :: filename()} |
{ok, {FileName :: filename(), binary()}} |
{error, Reason :: term()}
Creates a zip archive containing the files specified in
.
create/2
and create/3
are provided as synonyms
to resemble module
erl_tar
.
is a list of files, with paths relative
to the current directory, which are stored with this path in the
archive. Files can also be specified with data in binaries
to create an archive directly from data.
Files are compressed using the DEFLATE compression, as
described in the "Appnote.txt" file. However, files are
stored without compression if they are already compressed.
zip/2
and zip/3
check the file extension
to determine if the file is to be stored without compression.
Files with the following extensions are not compressed:
.Z
, .zip
, .zoo
, .arc
, .lzh
,
.arj
.
It is possible to override the default behavior and control
what types of files that are to be compressed by using options
{compress,
and
{uncompress,
. It is also possible to use
many compress
and uncompress
options.
To trigger file compression, its extension must match with the
compress
condition and must not match the
uncompress
condition. For example, if compress
is
set to ["gif", "jpg"]
and uncompress
is set to
["jpg"]
, only files with extension "gif"
are
compressed.
Options:
cooked
By default, this function opens the
zip file in mode raw
, which is faster but does not allow
a remote (Erlang) file server to be used. Adding cooked
to the mode list overrides the default and opens the zip file
without the raw
option. The same applies for the files
added.
verbose
Prints an informational message about each added file.
memory
The output is not to a file, but instead as a tuple
{
. The binary is a full zip
archive with header and can be extracted with, for example,
unzip/2
.
{comment, Comment }
Adds a comment to the zip archive.
{cwd, CWD }
Uses the specified directory as current work directory
(cwd
). This is prepended to filenames when adding them,
although not in the zip archive (acting like
file:set_cwd/1
in Kernel, but without
changing the global cwd
property.).
{compress, What }
Controls what types of files to be compressed. Defaults to
all
. The following values of What
are allowed:
all
All files are compressed (as long
as they pass the uncompress
condition).
[Extension ]
Only files with exactly these extensions are compressed.
{add,[Extension ]}
Adds these extensions to the list of compress extensions.
{del,[Extension ]}
Deletes these extensions from the list of compress extensions.
{uncompress, What }
Controls what types of files to be uncompressed. Defaults to
[".Z", ".zip", ".zoo", ".arc", ".lzh", ".arj"]
.
The following values of What
are allowed:
all
No files are compressed.
[Extension ]
Files with these extensions are uncompressed.
{add,[Extension ]}
Adds these extensions to the list of uncompress extensions.
{del,[Extension ]}
Deletes these extensions from the list of uncompress extensions.
zip_close(ZipHandle) -> ok | {error, einval}
ZipHandle = handle()
Closes a zip archive, previously opened with
zip_open/1,2
.
All resources are closed, and the handle is not to be used after
closing.
zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason}
ZipHandle = handle()
Result = file:name() | {file:name(), binary()}
Reason = term()
zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason}
FileName = file:name()
ZipHandle = handle()
Result = file:name() | {file:name(), binary()}
Reason = term()
Extracts one or all files from an open archive.
The files are unzipped to memory or to file, depending on
the options specified to function
zip_open/1,2
when opening the archive.
zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason}
Result = [zip_comment() | zip_file()]
ZipHandle = handle()
Reason = term()
Returns the file list of an open zip archive. The first returned element is the zip archive comment.
zip_open(Archive) -> {ok, ZipHandle} | {error, Reason}
Archive = file:name() | binary()
ZipHandle = handle()
Reason = term()
zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason}
Archive = file:name() | binary()
ZipHandle = handle()
Options = [Option]
Option = cooked | memory | {cwd, CWD :: file:filename()}
Reason = term()
Opens a zip archive, and reads and saves its directory. This
means that later reading files from the archive is
faster than unzipping files one at a time with
unzip/1,2
.
The archive must be closed with
zip_close/1
.
The
is closed if the
process that originally opened the archive dies.