ぼくは電子書籍の作成において、「でんでんコンバーター」を使ってEPUBを作っています。

電書ちゃんのでんでんコンバーター - でんでんコンバーター

 EPUBファイルをテキスト エディターにドラッグ&ドロップすると、先頭がマジック ナンバー「PK」で始まっていて、zipファイルであると見当が付きます。じっさい、拡張子を.zipに変えてやって、Windowsで右クリックして「すべて展開」をしてやると、xhtmlなどのファイルを含むフォルダーに展開されます。

 話は戻りますが、EPUBを作成したら、<idpf>EPUB Validatorなどのツールを使ってEPUBを検証します。でんでんマークダウンで原稿を書いて、でんでんコンバーターで変換する限り、まずエラーは起きませんが、画像タグのファイル名の打ち間違い、見出しレベルの乱れなどで、まれに検証エラーが発生します。この場合ValidatorはEPUBの中身のファイルについてエラーメッセージを出すので、EPUBを展開してみたくなります。

 EPUBの圧縮を伸長して中身を見たとしても、直接xhtmlファイルをいじるのは邪道で、ソース ファイルから修正してでんでんコンバーターで変換しなおすべきだと思います。ただ、好奇心で上記のフォルダーをzip圧縮して拡張子を.epubに戻してみても、正規のEPUBにはなりません。再度<idpf>EPUB Validatorで検証し直すと、下のようなエラーになります。

「Mimetype file entry is missing or is not the first file in the archive.」
「File 'META-INF/container.xml could not be found.」

 mimetypeというファイルも、META-INF/container.xmlというファイルも、見た目上あるので、変な感じがします。
 これは、mimetypeというフォルダーをzipコンテナの先頭に、圧縮率ゼロで置かなければならず、zipファイルにエクストラのヘッダー情報があってはならない、という要件を満たさなければならないためです。ということをぼくは、下の森さんのブログで知りました。

Sus scrofa liaodongensis: EPUB ZIP コンテナの作り方

 作業としては以下のコマンドラインを叩けばOKです。
(Windowsの場合はzip.exeのインストールが必要です)

 $ cd nantoka
 $ zip -0 -X ../nantoka.epub mimetype # mimetypeファイルを圧縮率ゼロ、余計なヘッダー無しで圧縮し、nantoka.epubを作る
 $ zip -r ../nantoka.epub -x mimetype # nantoka.epubに残りのファイルを追加する

 それで、これぐらいのコマンドラインは別に手で叩けばいいですし、バッチファイル化するのもカンタンです。また、以下のようなデスクトップアプリもあります。

ePubPack download | SourceForge.net

(外国のサイトあるあるですが、変なだましリンクが多いので注意!)

 ですが、ぼくは昨日、Perlで出来ることは全部Perlでやると決めたので、今日はこれをPerl化してみようと思います。今回はArchive::Zipというモジュールを使います。ないばあいはCPANからインストールします。

Archive::Zip - search.cpan.org

 プログラムはこんな感じです。

#! /usr/local/bin/perl
# zipEpub.pl -- EPUBファイル圧縮

use strict;
use warnings;
use 5.10.0;

use Archive::Zip;
use Cwd;

my $cwd = cwd(); # カレントディレクトリの絶対パス名
$cwd =~ m{([^/]+)$}; # カレントディレクトリのディレクトリ名
my $rwd = $1;
my $zipFile = $cwd.'/../'.$rwd.'.epub'; # ひとつ上の階層にディレクトリ名.epubという名前で置く
die "$zipFile already exists" if -f $zipFile; # すでにある場合は死ぬ

my $zip = Archive::Zip->new(); # 新規Zipオブジェクトを作る
my $mime = $zip->addFile ('mimetype'); # mimetypeを追加
$mime->desiredCompressionLevel ( 0 ); # -0 # 圧縮率0で圧縮
$zip->writeToFileNamed( $zipFile ); # ファイルを書き出す

$zip = Archive::Zip->new( $zipFile ); # 既存のzipファイルを読み込む
my $pred = sub { not /^mimetype$/ }; # ディレクトリからファイルを取り出すクライテリアを決める。今回は「mimetypeでなかったら」
$zip->addTree ('.', '', $pred ); # カレントディレクトリ以降のツリーを、mimetypeでなければZipに追加する。
$zip->overwrite(); # ファイルを上書きする

 EPUBをほぐしたディレクトリの中で上記のプログラムを起動すれば普通に元通りのEPUBが出来ます。
 この場合はアキラカにバッチファイルやコマンドラインの方がカンタンですが、今回はArchive::Zipの練習も兼ねてここまで。