Is there a way to convert a
zip archive to a
tar archive without extracting to a temporary directory first? (and without writing my own implementation of
This is now available as installable command from PyPI, see the end of this post.
I don't know of any "standard" utility that does so, but when I needed this functionality I wrote the following Python script to go from ZIP to Bzip2 compressed tar archives without extracting anything to disk first:
#! /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 output_file_name = os.path.splitext(input_file_name) + '.tar.bz2' main(input_file_name, output_file_name)
Just save it to
zip2tar and make it executable or save it to
zip2tar.py and run
python zip2tar.py. Provide the ZIP filename as an argument to the script, the output filename for
xyz.zip will be
The Bzip2 compressed output is normally much smaller than the zip file because the latter doesn't use compression patterns over multiple files, but there is also less chance of recovering later file if something in the Bzip2 file is wrong.
If you don't want the output compressed, remove
.bz2 from the code.
If you have
pip installed in a python3 environment, you can do:
pip3 install ruamel.zip2tar
to get a
zip2tar commandline utility doing the above (disclaimer: I am the author of that package).
tar command deals with file systems. It's input is a list of files that it then reads from a file system (including a lot of metadata). You would need to present the zip file as a file system for the
tar command to read it.
One you have AVFS installed, then you can
mountavfs cd ~/.avfs/path/to/somefile.zip# tar -cvf /path/whatever.tar .
AVFS will fill in any information for the file system that is missing from the zip, like file ownership, that tar will pick up.
Here’s a small snippet that converts a ZIP archive to a matching TAR.GZ archive OnTheFly.
Convert ZIP archive to TAR archive on the fly
# 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 tarinfo.uid = tarinfo.gid = user 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)