akishin999の日記

調べた事などを書いて行きます。

Ruby で tar.gz を扱う

Ruby で tar.gz を扱う方法を調べたところ、archive-tar-minitar というライブラリと zlib の組合せが簡単そうでした。

archive-tar-minitar | RubyGems.org | your community gem host
http://rubygems.org/gems/archive-tar-minitar

というわけで使ってみたメモなど。

インストール

% gem install archive-tar-minitar

複数ファイルを tar.gz にまとめる

圧縮自体は zlib の GzipWriter を使います。

# -*- coding: utf-8 -*-

require 'zlib'
require 'archive/tar/minitar'

Zlib::GzipWriter.open('foo.tar.gz', Zlib::BEST_COMPRESSION) do |gz|
  out = Archive::Tar::Minitar::Output.new(gz)
  Find.find(File.expand_path('~/testdata/')) do |file|
    Archive::Tar::Minitar::pack_file(file, out)
  end
  out.close
end

tar.gz を展開する

展開する場合は GzipReader と組み合わせて使います。

# -*- coding: utf-8 -*-

require 'zlib'
require 'archive/tar/minitar'

Zlib::GzipReader.open('foo.tar.gz') do |gz|
  Archive::Tar::Minitar::unpack(gz, './foo')
end

tar.gz にファイルのパスを含めないようにする

上の方法で圧縮した場合、圧縮する際にファイルのフルパスを指定すると、展開する際にも中間のディレクトリが作成されてしまうようです。
これを回避するため、一旦カレントディレクトリを変更し、圧縮後に戻すようにしてみました。

他にもっといい方法があるのかもしれませんが・・・。

# -*- coding: utf-8 -*-

require 'zlib'
require 'archive/tar/minitar'

# 圧縮対象のディレクトリ
DIR_PATH = "~/testdata"

# 圧縮ファイルのパス
ARCHIVE_PATH = "/home/akishin/work/foo.tar.gz"


# カレントディレクトリを保存
current_dir = Dir::pwd
# カレントディレクトリを変更
Dir::chdir(File.expand_path(DIR_PATH))

Zlib::GzipWriter.open(ARCHIVE_PATH, Zlib::BEST_COMPRESSION) do |gz|
  out = Archive::Tar::Minitar::Output.new(gz)
  Dir.glob('./*') do |file|
    Archive::Tar::Minitar::pack_file(file, out)
  end
  out.close
end

# カレントディレクトリを復元
Dir::chdir(current_dir)

こんな感じで結構簡単に tar.gz 形式を扱う事ができました。