最初に一時ディレクトリに抽出せずにZip
アーカイブをtar
アーカイブに変換する方法はありますか? (そしてtar
またはunzip
の独自の実装を書かずに)
これはPyPIからインストール可能なコマンドとして利用できるようになりました。この投稿の最後を参照してください。
そうする「標準」ユーティリティは知りませんが、この機能が必要なときに、次のように書きましたPythonスクリプトをZipからBzip2圧縮tarアーカイブに、ディスクに何も抽出せずに移動します最初:
#! /usr/bin/env python
"""Zip2tar """
import sys
import os
from zipfile import ZipFile
import tarfile
import time
def main(ifn, ofn):
with ZipFile(ifn) as zipf:
with tarfile.open(ofn, 'w:bz2') as tarf:
for Zip_info in zipf.infolist():
#print Zip_info.filename, Zip_info.file_size
tar_info = tarfile.TarInfo(name=Zip_info.filename)
tar_info.size = Zip_info.file_size
tar_info.mtime = time.mktime(list(Zip_info.date_time) +
[-1, -1, -1])
tarf.addfile(
tarinfo=tar_info,
fileobj=zipf.open(Zip_info.filename)
)
input_file_name = sys.argv[1]
output_file_name = os.path.splitext(input_file_name)[0] + '.tar.bz2'
main(input_file_name, output_file_name)
Zip2tar
に保存して実行可能にするか、Zip2tar.py
に保存してpython Zip2tar.py
を実行するだけです。スクリプトの引数としてZipファイル名を指定すると、xyz.Zip
の出力ファイル名はxyz.tar.bz2
になります。
Bzip2圧縮出力は通常、Zipファイルよりもはるかに小さくなります。これは、後者が複数のファイルに対して圧縮パターンを使用しないためです。ただし、Bzip2ファイル内の何かが間違っている場合、後のファイルを復元する可能性も低くなります。
出力を圧縮したくない場合は、コードから:bz2
および.bz2
を削除してください。
pip
をpython3環境にインストールしている場合、次のことができます。
pip3 install ruamel.Zip2tar
上記のZip2tar
コマンドラインユーティリティを取得するには(免責事項:私はそのパッケージの作成者です)。
tar
コマンドはファイルシステムを扱います。入力は、ファイルシステムから読み込まれるファイルのリストです(多くのメタデータを含む)。 tar
コマンドで読み取るには、Zipファイルをファイルシステムとして提示する必要があります。
仮想ファイルシステム-AVFS を使用すると、すべてのプログラムで Fuse を使用して、標準のファイルシステムインターフェースを介してアーカイブファイルまたは圧縮ファイルを調べることができます。
avfs-Fuse readme およびいくつかの distributionshavepackages には、いくつかの詳細情報があります。
AVFSがインストールされている場合、次のことができます
mountavfs
cd ~/.avfs/path/to/somefile.Zip#
tar -cvf /path/whatever.tar .
AVFSは、tarが取得する、ファイルの所有権など、Zipにないファイルシステムの情報を入力します。
これは、Zipアーカイブを対応するTAR.GZアーカイブOnTheFlyに変換する小さなスニペットです。
その場でZipアーカイブをTARアーカイブに変換します
# File: Zip2tar.py
#
# Convert Zip archive to TAR.GZ archive.
#
# Written by Fredrik Lundh, March 2005.
# helpers (Tweak as necessary)
def getuser():
# return user name and user id
return "anonymous", 1000
def getmode(name, data):
# return mode ("b" or "t") for the given file.
# you can do this either by inspecting the name, or
# the actual data (e.g. by looking for non-ascii, non-
# line-feed data).
return "t" # assume everything's text, for now
#
# main
import tarfile
import zipfile
import glob, os, StringIO, sys, time
now = time.time()
user = getuser()
def fixup(infile):
file, ext = os.path.splitext(infile)
outfile = file + ".tar.gz"
dirname = os.path.basename(file)
print outfile
Zip = zipfile.ZipFile(infile, "r")
tar = tarfile.open(outfile, "w:gz")
tar.posix = 1
for name in Zip.namelist():
if name.endswith("/"):
continue
data = Zip.read(name)
if getmode(name, data) == "t":
data = data.replace("\r\n", "\n")
tarinfo = tarfile.TarInfo()
tarinfo.name = name
tarinfo.size = len(data)
tarinfo.mtime = now
tarinfo.uname = tarinfo.gname = user[0]
tarinfo.uid = tarinfo.gid = user[1]
tar.addfile(tarinfo, StringIO.StringIO(data))
tar.close()
Zip.close()
# convert all Zip files in the current directory
for file in glob.glob("*.Zip"):
fixup(file)