Debianパッケージ(.debファイル)は通常はdpkg
という低レベルパッケージマネージャがAPTという高レベルパッケージマネージャやそのGUIを提供するSynapticなどを通して使用し、パッケージの中身を直接取り出したい場合にはdpkg
の-x [.debファイルの場所] [展開先]
オプションを用いるのだが、このパッケージのファイル形式はディストリに依存しないツールを組み合わせることでも展開できるものとなっており、ここではその展開方法についてを扱う。
パッケージ自体の形式
binutilsとarコマンド
.debファイルはbinutils
と呼ばれるツール群の一部であるar
というコマンドで扱える一種の書庫ファイルの形式をとっている。
binutils
は、C言語系の言語のプログラムを実行可能な形式に変換する流れの中でコンパイラが中間形式としてアセンブリ言語にしたものを機械語に変換する役割のas
というアセンブラを含むため、コンパイラのGCCやClangから依存されている。
ar
コマンドもソフトウェアのビルドの過程で自動的に用いられることがあり、個々のソースファイルからコンパイルされた複数のオブジェクトファイル(.oファイル)群を一つのファイルにまとめた静的リンクライブラリのファイル(.aファイル)として主に使われ、独自の機能を提供する “ライブラリ” の類でそれを用いたプログラムをビルドするのに必要な “開発” パッケージ(ディストリによって異なるが末尾が-devel
や-dev
となる名前)の一部として提供される。
.debファイルの直接の中身
.debファイルは、ar
で扱える書庫としては以下の3つのファイルから成る。
debian-binary
: パッケージ形式のバージョンが書かれたテキストファイルcontrol.tar.xz
: メタデータ(依存関係などの情報やインストール時に実行されるスクリプトなどを含む)data.tar.xz
: パッケージの中身そのもの
以前は2つの書庫ファイルについて.tar.gz形式が用いられていたが、(ビルドされた時期が)新しいパッケージでは圧縮率の高い.tar.xz形式に移行している。
$ ar t /path/to/package.deb debian-binary control.tar.xz data.tar.xz
過渡期のパッケージではcontrol.tar.gz
が入っていたりする。
$ ar t /path/to/package.deb debian-binary control.tar.gz data.tar.xz
なお、古めのディストリで新しいディストリ向けのパッケージをインストールしようとするとcontrol.tar.xz
が処理できずに失敗することがある。
汎用的な展開スクリプト
引数に.debファイルの場所と追加で展開先ディレクトリ(省略時は現在の作業ディレクトリ)を指定して実行すると、その.debファイルの中身を指定ディレクトリ内に展開する。操作にはパイプを用いているため、一時ファイルは作成しない。
動作にはbinutils
パッケージが必要で、それ以外にもtar
やXZ Utilsなども用いられるがOSの基本部分として標準でインストールされていることが多いため、ない場合のみインストールする。
deb-unpacker.sh
ライセンス:MIT#! /bin/sh
# Debian package unpacker
# (C) 2018 kakurasan
# Licensed under MIT
if test -z "${1}"; then
echo "Usage: ${0} [DEB FILE] ([OUTPUT DIR])"
exit 1
fi
DEB="${1}"
OUTDIR="${2:-.}" # Default is the current directory
# Check for binutils
ar --version > /dev/null 2>&1
if test ${?} -ne 0; then
echo "ERROR: Package \"binutils\" is not installed."
exit 1
fi
# Check for input file
if ! test -f "${DEB}"; then
echo "ERROR: File \"${DEB}\" doesn't exist."
exit 1
fi
# Check whether debian-binary is present
ar t "${DEB}" 2>/dev/null | grep -E ^debian-binary$ >/dev/null
if test ${?} -ne 0; then
echo "ERROR: File \"${DEB}\" is not Debian package file."
exit 1
fi
# Create output directory
if ! mkdir -p "${OUTDIR}"; then
echo "ERROR: Could not create directory \"${OUTDIR}\"."
exit 1
fi
# Determine the compression program and unpack data.tar.*
DATA_TARBALL="$(ar t "${DEB}" 2> /dev/null | grep data.tar.)"
case "${DATA_TARBALL}" in
*.tar.xz)
ar p "${DEB}" data.tar.xz | tar -C "${OUTDIR}" -Jvxf -
;;
*.tar.bz2)
ar p "${DEB}" data.tar.bz2 | tar -C "${OUTDIR}" -jvxf -
;;
*.tar.gz)
ar p "${DEB}" data.tar.gz | tar -C "${OUTDIR}" -zvxf -
;;
*)
echo "ERROR: data.tar.{xz,bz2,gz} not found."
exit 1
;;
esac
# Done
echo "Successfully unpacked \"${DEB}\" into \"${OUTDIR}\"."