Add or replace a zip archive entry from the pipeline

Why We Need It

Problem: the standard Info-Zip's archiver assumes that the target archive entry file name should be the same as the real source file name. Though it may add or replace file from its standard input, this file is doomed to be called "-". It's not always what you want.

Linux-specific solution: symbolic links

Linux has a /proc filesystem. Opening a file /proc/$PID/fd/$N is equivalent to `dupping' the process' file descriptor into your application.

For any process, /proc/self is an alias of a /proc subdirectory for this process: not only when a file under /proc/self is opened directly, but also when a symbolic link is resolved.

It became a tradition to have /dev/stdin linking to /proc/self/fd/0, /dev/stdout to /proc/self/fd/1, and /dev/stderr to /proc/self/fd/2.

These features of the proc filesystem provide a way to trick the standard zip utility into reading its standard input while thinking that it's a named file.

First, the symbolic link is created (a random subdirectory of /tmp is the most appropriate place for it). The target would be /dev/stdin (or /proc/self/fd/0), and the name of the link itself is the desirable name of file in the archive:

DIR=`mktemp -d`
cd $DIR
ln -s /dev/stdin desiredName.txt

Then the standard zip archiver may be invoked in the pipeline:

do something hard | zip -FI ..../ desiredName.txt

It reads desiredName.txt and updates the archive, completely unaware that this file is its own standard input. Option -FI is required at least for some zip versions, or else it refuses to archive a FIFO (unnamed pipe pointed by desiredName.txt link is a FIFO, of course).

Zipput Makes It Easy

The pipeline below is all you need for the same task, if you installed zipput.

do something hard | zipput ..../ desiredName.txt


On the one hand, zipput is portable. On the other hand, it requires libzip. On the third hand... well, libzip is also portable.

If you have libzip, both library and header, at your system, something like

cc -o zipput zipput.c -lzip
would be enough to get zipput executable. Of course, you may prefer
gcc -pedantic -ansi -Wall -W -Werror \
-O4 -std=c89 -Wl,--strip-all zipput.c -lzip
But it doesn't make much of a difference, so why bother.

If you are lucky to have a Debian GNU/Linux Lenny system, there is a repository, kindly provided by Mobigroup. Anyway, it's worthy of having it it in your /etc/apt/sources.list, for much more useful things than Zipput.

deb lenny main contrib non-free
deb-src lenny main contrib non-free
Don't forget to install debian-mobigroup-keyring for package verification. Debian-like or debian-based distributions have some chance to work with many packages of this collection, especially with the trivial thingy like zipput.