Existe-t-il un moyen de convertir une zip
archive en tar
archive sans extraire au préalable dans un répertoire temporaire? (et sans écrire ma propre implémentation de tar
ou unzip
)
Existe-t-il un moyen de convertir une zip
archive en tar
archive sans extraire au préalable dans un répertoire temporaire? (et sans écrire ma propre implémentation de tar
ou unzip
)
Réponses:
Ceci est maintenant disponible en tant que commande installable de PyPI, voir la fin de ce post.
Je ne connais aucun utilitaire "standard" qui le fasse, mais quand j'ai eu besoin de cette fonctionnalité, j'ai écrit le script Python suivant pour passer de ZIP aux archives tar compressées Bzip2 sans extraire quoi que ce soit sur le disque d'abord:
#! /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)
Il suffit de l'enregistrer zip2tar
et de le rendre exécutable ou de l'enregistrer zip2tar.py
et de l'exécuter python zip2tar.py
. Fournissez le nom de fichier ZIP comme argument au script, le nom de fichier de sortie pour xyz.zip
sera xyz.tar.bz2
.
La sortie compressée Bzip2 est normalement beaucoup plus petite que le fichier zip car ce dernier n'utilise pas de modèles de compression sur plusieurs fichiers, mais il y a également moins de chances de récupérer un fichier ultérieur si quelque chose dans le fichier Bzip2 est incorrect.
Si vous ne voulez pas que la sortie soit compressée, supprimez :bz2
et .bz2
du code.
Si vous avez pip
installé dans un environnement python3, vous pouvez faire:
pip3 install ruamel.zip2tar
pour obtenir un zip2tar
utilitaire de ligne de commande faisant ce qui précède (avertissement: je suis l'auteur de ce package).
time
manque un import
.
time
commentaire, je mets à jour la réponse
La tar
commande traite des systèmes de fichiers. Son entrée est une liste de fichiers qu'il lit ensuite à partir d'un système de fichiers (y compris un grand nombre de métadonnées). Vous devrez présenter le fichier zip comme un système de fichiers pour que la tar
commande le lise.
Un système de fichiers virtuel - AVFS permettra à tout programme de regarder à l'intérieur des fichiers archivés ou compressés via une interface de système de fichiers standard via FUSE .
Il y a des informations détaillées dans le fichier Lisezmoi d'avfs-fuse et certaines distributions ont packages pour cela.
Un que vous avez installé AVFS, alors vous pouvez
mountavfs
cd ~/.avfs/path/to/somefile.zip#
tar -cvf /path/whatever.tar .
AVFS remplira toutes les informations du système de fichiers manquantes dans le zip, comme la propriété du fichier, que tar récupérera.
Voici un petit extrait qui convertit une archive ZIP en une archive TAR.GZ correspondante OnTheFly.
Conversion d'archive ZIP en archive TAR à la volée
# 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)