Introducing Tcl 8.7 Part 11: The ZIP virtual file system
This is the eleventh in a series of posts about new features in the upcoming version 8.7 of Tcl. It is the first of a pair of posts describing core support for treating ZIP archives as virtual file systems within Tcl. This post focuses on base operations dealing with existing ZIP archives. The next describes the creation of ZIP archives and their use for building zipkits and single file executables.
To take Tcl 8.7 for a spin, you can download a pre-alpha binary for your platform. Alternatively, you can build it yourself from the
core-8-branch
branch in the Tcl fossil repository.
With Tcl 8.6, access to files in ZIP archives was already possible. Tcl itself offered the ability to compress and decompress data with the zlib
command. The zipfile
module in tcllib
then made use of these to permit access to files within an archive.
Tcl 8.7 goes beyond these capabilities by treating ZIP archives as mountable virtual file systems (VFS). This makes access to the files within the archive much simpler through the standard Tcl channel commands open
, gets
etc.
Mounting ZIP archives
The first step to accessing ZIP archives is to mount them as a Tcl VFS. This is done with the zipfs mount
command.
% zipfs mount mnt demo.zip
This results in the archive demo.zip
being mounted as a VFS under the path zipfs:/mnt
.
The root of all ZIP file systems is given by the zipfs root
command.
% zipfs root
zipfs:/
This root is platform-specific, zipfs:/
on Windows and //zipfs:/
on Unix(y) systems.
Naturally, you can mount multiple archives or even the same archive multiple times. The mount points of course have to be different but one can be nested inside another. For example,
% zipfs mount mnt2 demo.zip
% zipfs mount mnt/nested demo2.zip
Invoking zipfs mount
without any arguments will return the currently mounted ZIP archives as a flat list of mount points and the archive file path.
% zipfs mount
zipfs:/mnt demo.zip zipfs:/mnt/nested demo2.zip zipfs:/mnt2 demo.zip
ZIP archives may be protected with a password. In that case the password must be supplied as the last argument to the command.
When no longer needed the each VFS should be unmounted with zipfs unmount
.
% zipfs unmount mnt2
% zipfs unmount mnt/nested
% zipfs mount
zipfs:/mnt demo.zip
Introspecting archives
Once mounted, the archives can be introspected.
The zipfs list
command returns a list of the files in the ZIP file system. Optionally, regular expression or glob wildcard patterns may be specified to filter the returned paths.
% zipfs list
zipfs:/mnt/demo zipfs:/mnt zipfs:/mnt/demo/subdir/file.txt zipfs:/mnt/demo/subdir zipfs:/mnt/demo/demo.txt
% zipfs list *.txt
zipfs:/mnt/demo/subdir/file.txt zipfs:/mnt/demo/demo.txt
% zipfs list -glob *.txt
zipfs:/mnt/demo/subdir/file.txt zipfs:/mnt/demo/demo.txt
% zipfs list -regexp {\.txt$}
zipfs:/mnt/demo/subdir/file.txt zipfs:/mnt/demo/demo.txt
Notice there is no mount point specified above. The command lists all files and directories under the ZIP VFS root. To restrict to a specific archive, specify it as a pattern.
A similar command returns a list of all file paths under a specific directory.
% zipfs find zipfs:/mnt/demo/subdir
zipfs:/mnt/demo/subdir/file.txt
TIP: The zipfs find
command will work with any file system, not just ZIP VFS'es.
Since the ZIP archive is mounted as a Tcl VFS, standard Tcl commands for retrieving generic file information can be used. For example,
% file size zipfs:/mnt/demo/demo.txt
12
% clock format [file atime zipfs:/mnt/demo/demo.txt]
Sun Aug 23 12:33:24 IST 2020
The zipfs info
command returns additional information that is specific to the ZIP archive format.
% zipfs info zipfs:/mnt/demo/demo.txt
demo.zip 12 14 50
The returned list contains the name of the ZIP archive (as originally passed), the original file size, the compressed file size and the offset of the file's compressed data within the ZIP archive. (As an aside, note in our example that the "compressed" size is greater than the actual size as often happens for small files.)
File I/O
Data transfer from compressed files in the archive is achieved through the standard Tcl channel I/O commands.
% set chan [open zipfs:/mnt/demo/demo.txt]
zipfs_32_1
% gets $chan
Demo file
% close $chan
You can also open the file for writing. However, the ZIP VFS does not support the append mode.
Coming up
Having described the basics of access to ZIP archives, in the next post I will illustrate the use of the new features for creating ZIP archives, zipkits and single-file executables.