Introducing Tcl 8.7 Part 11: The ZIP virtual file system

Published

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 the source distribution. Binary distributions for Windows are available from magicsplat and BAWT.

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.

References

  1. TIP 430: Add basic ZIP archive support to Tcl

  2. zipfs man page