tar形式は、ファイルアーカイブのフォーマットの一つです。本来tarはファイルアーカイブのみで圧縮の機能はありませんが、Pythonではtarfileモジュールを使ってファイルアーカイブとデータ圧縮まで行うことが可能です。今回はこのモジュールをの基本的な使い方についてまとめます。
確認した環境
- OS: Ubuntu 16.04LTS
- Python: ver3.7.0
tarファイルフォーマットとは
tar形式は、ファイルアーカイブのフォーマットの一つで、UNIX系OSでは標準のフォーマットです。Pythonではtarfileモジュールを使ってファイルのアーカイブ化を実現しますが、圧縮アルゴリズム(gzip、bz2、および lzma)を選択して、データ圧縮も可能です。
尚、ZIPの際はひと工夫が必要でしたが、tarfileモジュールはディレクトリ圧縮も可能です。
この記事で使うフォルダ構成の概要
この記事では、以下のフォルダ構成を例にします。
- カレントディレクトリ:/home/rensyu
- 圧縮ファイルパス:/home/rensyu/testdir2.tar.gz
- 圧縮ファイルのフォルダ構成:testdir2.tar.gz
.
├── sample0
│ └── sample01.txt
├── sample1.txt
└── sample2.txt
TarFileオブジェクト生成
tarアーカイブファイルの読み込み/書き込みは、まずopen()メソッドを使ってTarFileオブジェクトを生成します。
tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
引数の設定を以下に示します。mode設定はcompressionパラメータの組み合わせを考えるともっとたくさん設定があるのですが、多すぎるのでここでは主なものだけを記載しました。(詳細は公式サイトを参照)
引数 | 説明 |
---|---|
name | 開きたいアーカイブファイルのパスを文字列で設定 |
mode = filemode [:compression] | モード設定 'r' または 'r:*' : 読み込みモード(透過的圧縮(※1))(デフォルト・推奨) 'x' または'x:' : 新規書き込みモード(圧縮なし)(※2) 'a'または'a:' :追加モード(圧縮なし)(※3) 尚、compressionは、gz, bz2, xyを設定可能(一部例外あり) |
その他注記事項は以下です。
※1)透過的圧縮(transparent compress): 何かわからなかったので調べると、データを圧縮した状態のまま内容にアクセスできるような圧縮のこと、のようです。(こちらのサイト様を参考にさせて頂きました)
※2)既にファイルが存在していればFileExistsErrorが返ります。
※3)ファイルが存在しなければ新規作成
尚、指定した圧縮方式が開こうとするファイルに対し適切でないとReadErrorとなります。また指定した圧縮方式がサポートされていない場合CompressionErrorとなります。
ここで、TarFileオブジェクトについてもう少し掘り下げてみます。
以下のコードは、tarアーカイブファイルに含まれるファイルの一覧を出力するものです。
>>> import tarfile
# tarfileオブジェクトを生成
>>> tar = tarfile.open('./testdir2.tar.gz', 'r')
# tarアーカイブに含まれるファイル/フォルダ名を取得
>>> for tarinfo in tar:
... tarinfo.name
...
'./testdir2'
'./testdir2/sample0'
'./testdir2/sample0/sample01.txt'
'./testdir2/sample1.txt'
'./testdir2/sample2.txt'
# tarfileオブジェクトをクローズ
>>> tar.close()
このコードでtarfileオブジェクトの中身がなんとなく分かると思いますが、もう少し順を追って見ていきます。TarFileオブジェクトをリスト化してみると、、、
>>> list(tar)
[<TarInfo './testdir2' at 0x7f23ebc9e4f8>,
<TarInfo './testdir2/sample0' at 0x7f23ece17b38>,
<TarInfo './testdir2/sample0/sample01.txt' at 0x7f23ece17d90>,
<TarInfo './testdir2/sample1.txt' at 0x7f23ebc9e1d8>,
<TarInfo './testdir2/sample2.txt' at 0x7f23ebc9e2a0>]
中身はTarInfoオブジェクトの集合で構成されています。これらのname属性を確認すると以下のようにフォルダ名が得られます。
# 例えば、最初の要素のname属性を確認します
>>> list(tar)[0].name
'./testdir2'
ちなみに、TarFileオブジェクト生成はwithステートメントで記載することも出来ます。withステートメントで書いたコードは以下。
>>> import tarfile
>>> with tarfile.open('./testdir2.tar.gz', 'r:*') as tar:
... for tarinfo in tar:
... tarinfo.name
...
'./testdir2'
'./testdir2/sample0'
'./testdir2/sample0/sample01.txt'
'./testdir2/sample1.txt'
'./testdir2/sample2.txt'
以降、tarfileオブジェクトの生成はwithステートメントで記載します。
tarファイルの展開
extractall()メソッドで展開できます。
TarFile.extractall(path=".", members=None, *, numeric_owner=False)
第一引数にファイルを展開する場所(フォルダ)を指定します。指定がなければカレントフォルダに展開されます。
>>> import tarfile
>>> with tarfile.open('./testdir2.tar.gz', 'r:*') as tar:
... tar.extractall('./extracted')
結果を確認します。設定したとおりextractedフォルダに展開されています。
/home/rensyu$ tree
.
├── extracted ← ここに展開されました
│ └── testdir2
│ ├── sample0
│ │ └── sample01.txt
│ ├── sample1.txt
│ └── sample2.txt
└── testdir2.tar.gz
tarファイルの作成
tarfile.open()メソッドでTarFileオブジェクトを書き込みモード(圧縮モードはここではgzip)で開いた後に、add()メソッドで圧縮したいファイルを追加していきます。ちなみに拡張子は、tarフォーマットでアーカイブしてgzipで圧縮しているので‘.tar.gz’と表記しています。
尚、ZipFileオブジェクトと異なり、フォルダでもファイルでもtarファイルを作成できます。
ここでは、上記例で展開したtestdir2フォルダを丸ごとgzipで圧縮する例を記載します。
>>> import tarfile
>>> with tarfile.open('./compressed.tar.gz', 'w:gz') as tar:
... tar.add('./extracted/testdir2')
...
>>>
フォルダ構成を確認してみます。
/home/rensyu$ tree
.
├── compressed.tar.gz ← ここにtarファイルが作成されました
├── extracted
│ └── testdir2
│ ├── sample0
│ │ └── sample01.txt
│ ├── sample1.txt
│ └── sample2.txt
└── testdir2.tar.gz
まとめ
今回はtarファイルフォーマットによるファイルアーカイブとデータ圧縮の基本についてまとめました。