Existe uma maneira de converter um zip
arquivo em um tar
arquivo sem extrair primeiro um diretório temporário? (e sem escrever minha própria implementação de tar
ou unzip
)
Existe uma maneira de converter um zip
arquivo em um tar
arquivo sem extrair primeiro um diretório temporário? (e sem escrever minha própria implementação de tar
ou unzip
)
Respostas:
Agora está disponível como comando instalável do PyPI, consulte o final deste post.
Não conheço nenhum utilitário "padrão" que o faça, mas quando precisei dessa funcionalidade, escrevi o seguinte script Python para ir dos arquivos tar compactados ZIP para Bzip2 sem extrair nada para o disco primeiro:
#! /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)
Apenas salve-o zip2tar
e torne-o executável ou salve-o zip2tar.py
e execute-o python zip2tar.py
. Forneça o nome do arquivo ZIP como argumento para o script, o nome do arquivo de saída xyz.zip
será xyz.tar.bz2
.
A saída compactada do Bzip2 é normalmente muito menor que o arquivo zip, porque este último não usa padrões de compactação em vários arquivos, mas também há menos chances de recuperar arquivos posteriores se algo no arquivo Bzip2 estiver errado.
Se você não deseja compactar a saída, remova :bz2
e .bz2
do código.
Se você pip
instalou em um ambiente python3, pode:
pip3 install ruamel.zip2tar
para obter um zip2tar
utilitário de linha de comando fazendo o acima (aviso: eu sou o autor desse pacote).
time
falta de um import
.
time
comentário, eu atualizar a resposta
O tar
comando lida com sistemas de arquivos. Sua entrada é uma lista de arquivos que são lidos em um sistema de arquivos (incluindo muitos metadados). Você precisaria apresentar o arquivo zip como um sistema de arquivos para o tar
comando lê-lo.
Um sistema de arquivos virtual - AVFS permitirá que qualquer programa procure dentro de arquivos compactados ou arquivados por meio de uma interface padrão de sistema de arquivos via FUSE .
Há algumas informações detalhadas no leia-me do avfs-fuse e algumas distribuições têm pacotes para isso.
Se você tiver o AVFS instalado, poderá
mountavfs
cd ~/.avfs/path/to/somefile.zip#
tar -cvf /path/whatever.tar .
O AVFS preencherá todas as informações do sistema de arquivos ausentes do zip, como a propriedade do arquivo, que o tar será capturado.
Aqui está um pequeno trecho que converte um arquivo ZIP em um arquivo TAR.GZ correspondente no OnTheFly.
Converter arquivo ZIP em arquivo TAR em tempo real
# 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)