¿Hay alguna manera de convertir un zip
archivo en un tar
archivo sin extraerlo primero a un directorio temporal? (y sin escribir mi propia implementación de tar
o unzip
)
¿Hay alguna manera de convertir un zip
archivo en un tar
archivo sin extraerlo primero a un directorio temporal? (y sin escribir mi propia implementación de tar
o unzip
)
Respuestas:
Ahora está disponible como comando instalable desde PyPI, vea el final de esta publicación.
No conozco ninguna utilidad "estándar" que lo haga, pero cuando necesitaba esta funcionalidad, escribí el siguiente script de Python para pasar de archivos comprimidos tar a ZIP a Bzip2 sin extraer nada al disco primero:
#! /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)
Simplemente guárdelo zip2tar
y hágalo ejecutable o guárdelo zip2tar.py
y ejecútelo python zip2tar.py
. Proporcione el nombre de archivo ZIP como argumento para el script, el nombre de archivo de salida xyz.zip
será xyz.tar.bz2
.
La salida comprimida de Bzip2 normalmente es mucho más pequeña que el archivo zip porque este último no usa patrones de compresión en varios archivos, pero también hay menos posibilidades de recuperar el archivo posterior si algo en el archivo Bzip2 está mal.
Si no desea comprimir la salida, elimine :bz2
y .bz2
del código.
Si ha pip
instalado en un entorno python3, puede hacer:
pip3 install ruamel.zip2tar
para obtener una zip2tar
utilidad de línea de comandos haciendo lo anterior (descargo de responsabilidad: soy el autor de ese paquete).
time
carece de un import
.
time
comentario, actualizo la respuesta
El tar
comando trata con los sistemas de archivos. Su entrada es una lista de archivos que luego lee de un sistema de archivos (incluidos muchos metadatos). Debería presentar el archivo zip como un sistema de archivos para que el tar
comando lo lea.
Un sistema de archivos virtual: AVFS permitirá que cualquier programa busque archivos comprimidos o comprimidos a través de una interfaz de sistema de archivos estándar a través de FUSE .
Hay información detallada en el archivo Léame avfs-fuse y algunas distribuciones tienen paquetes para ello.
Uno tiene instalado AVFS, luego puede
mountavfs
cd ~/.avfs/path/to/somefile.zip#
tar -cvf /path/whatever.tar .
AVFS completará cualquier información para el sistema de archivos que falta en el archivo zip, como la propiedad del archivo, que recogerá tar.
Aquí hay un pequeño fragmento que convierte un archivo ZIP en un archivo TAR.GZ coincidente en OnTheFly.
Convierte archivos ZIP a archivos TAR sobre la marcha
# 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)