試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

圧縮の余地があるPDFファイルをXZ圧縮してPDFビューアから開く

圧縮の余地があるPDFファイルをできるだけ縮めておきつつ簡単に開けるようにしたい

Webなどから入手したPDFファイルは、ほとんどの場合において読み込みしか行わず、変更することはない。また、元々圧縮されているタイプのファイル形式ではあるものの、ファイルにもよるが、圧縮の余地が多くあって圧縮をかけると結構縮むケースもある。
そこで、残しておきたいPDFファイルを(高圧縮率かつ伸長がやや軽めな)XZ形式で圧縮しておいてこれをビューア側からうまく開く方法があれば便利。
(2010/1/18)Web上の色々なPDFファイルを実際に圧縮して圧縮率を調べるテストを「色々なPDFファイルをgzip/bzip2/XZ圧縮してみるテスト」でgzipやbzip2との比較も含めて行った。

xzcatとパイプで標準入力からデータを受け付ける

Adobe ReaderとOkularは標準入力を指定して開ける

XZ UtilsのxzcatはXZ圧縮されたファイル群をそれぞれ伸長してその結果を結合し、標準出力に出力する。これを用いて1つのXZ圧縮済みPDFファイル(*.pdf.xz)を開いてパイプでビューア側に標準入力として(伸長後の生PDFデータを)渡せればうまく処理できる。
これにはビューア側が起動時の引数として標準入力を指定してそれを受け取れることが必要だが、Adobe Reader(Adobe社によるビューア)とKDEOkularの2つは「-」指定で問題なく動作してくれた。

(Adobe ReaderでXZ圧縮済みPDFファイルを開く)
$ xzcat [.pdf.xzファイルの場所] | acroread -
(OkularでXZ圧縮済みPDFファイルを開く)
$ xzcat [.pdf.xzファイルの場所] | okular -
Evinceは対応していないがスクリプトで対処可

残念ながら、GTK+アプリケーションのEvince(ドキュメント・ビューア)では標準入力をサポートしていないようで、開けなかった。バグとしても出ているが
https://bugzilla.gnome.org/show_bug.cgi?id=340467#c2
では内部的な動作の事情もあって修正予定なしとされている。
そこで下のようなスクリプト(dashでもOK)を作成した。動作にはZenityが必要。
これを用いると、引数に指定した場所の.pdf.xzファイルを一時ディレクトリの中に伸長し、それをEvinceで開き、終了後に一時ディレクトリごと消す。引数がなければGUIのファイル選択ダイアログから.pdf.xzファイルを選択することもできる。
[任意]ファイル名: open-xzed-pdf-with-evince.sh ライセンス: MIT

#! /bin/sh

# Open XZ'ed PDF file with Evince (GNOME Document Viewer)
# Licensed under MIT
# (C) 2010 kakurasan
# version 20100115

PATH=/bin:/usr/bin

die()
{
  zenity --error --title "Error" --text "${1}"
  exit 1
}

# check zenity
if ! zenity --version >/dev/null; then
  echo "Error: zenity is not installed"
  exit 1
fi

# input file
if [ ${#} -eq 1 ]; then
  # relative path ==> absolute path
  XZEDPDFFILE="$(cd "$(dirname "${1}")" && pwd)/$(basename "${1}")"
else
  XZEDPDFFILE="$(zenity --file-selection --title "Open .pdf.xz file")"
  if [ ${?} -ne 0 ]; then
    # cancel
    exit 0
  fi
fi
[ -f "${XZEDPDFFILE}" ] || die "File \"${XZEDPDFFILE}\" does not exist"

# test
xzcat "${XZEDPDFFILE}" > /dev/null 2>&1 || die "not XZ file"

# tmpdir
TEMPDIR=$(mktemp --tmpdir -d xzed-pdf-evince.XXXXXXXX)
[ ${?} -eq 0 ] || die "cannot create tempdir"
cd "${TEMPDIR}"

# uncompress
PDFFILE="$(basename "${XZEDPDFFILE}" .xz)"
xzcat "${XZEDPDFFILE}" > "${PDFFILE}" || die "xzcat failed"

# open with Evince
evince "${PDFFILE}" || die "evince failed"

# cleanup
rm "${TEMPDIR}" -fr

他のビューアでも同じようにすることはできるが、(一時ディレクトリがtmpfsでない限り)余計なディスク読み書きを発生させるのでおすすめはしない。

関連記事:

使用したバージョン:

  • Adobe Reader 9.3
  • Okular 0.9.2
  • Evince 2.28.1
  • XZ Utils 4.999.9beta