13
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ディスク容量節約:tar.bz2やtar.gzをtar.xzに変更するスクリプト&解説

Last updated at Posted at 2014-03-13

あらまし

先日、Jenkins で保存していたビルド成果物がディスク領域を圧迫してしまい、Jenkinsが止まってしまいました。
早急にディスク領域を空けないとプロジェクトに支障をきたしてしまいます。

成果物をfoo.tar.bz2のように、tar+bzip2形式で保存したので、これをより圧縮率の高いtar+xz形式に変換することで、ディスク領域を空けることができました。

本題

Linuxカーネルのソースコードを使って、実際にやってみましょう。

.tar.bz2の場合

recompress-bz2.sh に tar+bzip2形式のファイルを食わせればOKです。

recompress-bz2.sh
# !/bin/bash -ue

BZ2=$1
XZ=${1%.bz2}.xz

trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15

if bzcat $BZ2 | xz -v > $XZ
then
    trap "echo $0 trapped." 1 2 3 15
    rm -f $BZ2
else
    rm -f $XZ
fi
.tar.bz2の場合
$ wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.12.tar.bz2
$ ls -lh linux-3.12.tar.bz2
-rw-r--r-- 1 hogefoo hogefoo 87M 11月  4 08:47 linux-3.12.tar.bz2
$ sh recompress-bz2.sh linux-3.12.tar.bz2
  100 %        75.2 MiB / 518.8 MiB = 0.145   2.0 MiB/s       4:16             
$ ls -lh linux-3.12.tar.*
-rw-r--r-- 1 hogefoo hogefoo 76M  3月 14 01:00 linux-3.12.tar.xz

もとの.tar.bz2ファイルは消え、.tar.xzファイルができています。
容量はざっと 11MB減りました

.tar.gzの場合

.tar.bz2の場合とあんまり変わりません。

recompress-gz.sh
# !/bin/bash -ue

GZ=$1
XZ=${1%.gz}.xz

trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15

if zcat $GZ | xz -v > $XZ
then
    trap "echo $0 trapped." 1 2 3 15
    rm -f $GZ
else
    rm -f $XZ
fi
tar.gzの場合
$ wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.12.tar.gz
$ ls -lh linux-3.12.tar.gz
-rw-r--r-- 1 hogefoo hogefoo 110M 11月  4 08:47 linux-3.12.tar.gz
$ sh recompress-gz.sh linux-3.12.tar.gz
  100 %        75.2 MiB / 518.8 MiB = 0.145   2.0 MiB/s       4:13             
$ ls -lh linux-3.12.tar.*
-rw-r--r-- 1 hogefoo hogefoo 76M  3月 14 01:17 linux-3.12.tar.xz

こちらは34MB減っています

解説

tar形式

そもそも、foo.tar.bz2というのは、foo.tarというtar形式のファイルをbzip2で圧縮したファイルです。
tar形式に圧縮機能はなく、コンテナとしてファイルとそのメタ情報を記録する機能しかありません

なのでbzip2やgzipの圧縮から解いて、ただのtar形式にしてからxzで圧縮すれば、tar.xzの出来上がりです。

tar.bz2やtar.gzからtarへ

bzcatzcatを用いると、 簡単に.tar.bz2 や.tar.gzをtar形式として標準出力に流す ことができます。

$ bzcat foo.tar.bz2 > foo.tar
$ zcat bar.tar.gz > bar.tar

tarからtar.xzへ

xz -で、 標準入力をxzで圧縮して標準出力に流すことができます

$ cat foo.tar | xz - > foo.tar.xz

recompress-bz2.shrecompress-gz.shでは、-vを付けて、進捗を表示させています。

tar.bz2やtar.gz から、tar.xzへ

標準出力へtar形式を流す方法と、標準入力をxzで圧縮する方法がわかりました。
あとはくっつけるだけです。

$ bzcat foo.tar.bz2 | xz - > foo.tar.xz
$ zcat bar.tar.gz | xz - > bar.tar.xz

おしまい。

蛇足

拡張子

Bashの機能を用いて、拡張子の変換を行ってます。
POSIX Shellでできるかどうかは調べてません。

追記 コメント欄より

POSIX シェルでも出来ます!

とのことです。THX! @magicant

GZ=$1
XZ=${1%.gz}.xz

${1%.gz}$1の末尾から.gzを削った結果を返します。

Ctrl-Cの対応

trapを用いて、Ctrl-Cで止められた時の処理をしています。

Linuxの場合
trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15

または

他OSではシグナルの番号が違うことがあるので名前で指定
trap "echo $0 trapped.; rm -f $XZ" HUP INT QUIT TERM

第一引数はシグナルを受けたときに実行する処理、
第二引数はシグナルを示しています。

ここでシグナルは番号、名前の両方が使えますが、
OSによって番号がは異なることがあるため、名前を用いた方が移植性が高いようです。
コメント欄参照。 THX! @magicant

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

一般的に、1 2 3 15をおさえておけばよいそうです。

また、再圧縮が終わってrm -rf $GZする前にtrap "echo $0 trapped." 1 2 3 15として、削除処理上書きして無効にすることで、せっかく出来たtar.xzファイルを削除してしまわないようにしています。

他の方法

tar xvzfなりtar xvjfなりで解凍してからtar xvJfで圧縮することもできますが、
ディスク領域と時間の無駄なのであんまりオススメできません。

参考

trapについては、以下を参考にしました。
[シグナルと trap コマンド - UNIX & Linux コマンド・シェルスクリプト リファレンス](http://shellscript.sunone.me/signal_and_trap.html シグナルと trap コマンド - UNIX & Linux コマンド・シェルスクリプト リファレンス)

#!/bin/bash -ueについては、 @youcune の以下の記事を参考にしました
[シェルスクリプトを書くときはset -euしておく](http://qiita.com/youcune/items/fcfb4ad3d7c1edf9dc96 シェルスクリプトを書くときはset -euしておく)

bash, bzcat, zcat, xzについては、man bash, man bzip2, man gzip, man xzを参考にしました。

おことわり

異常処理とか適当なので、データ消失等の事故については自己責任でおねがいします。
もし危ないところに気づいたら編集リクエストなりコメントなりで御指摘いただけると幸いです。

また、語の統一がかなり適当なので、あとで編集するかもです。
大意は変わらないはずです。

あしからず。

13
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?