Existe uma maneira de converter um zip em um tar sem extraí-lo para o sistema de arquivos?

13

Existe uma maneira de converter um zip archive em tar archive sem extrair para um diretório temporário primeiro? (e sem escrever minha própria implementação de tar ou unzip )

    
por immibis 24.07.2014 / 07:11

3 respostas

10

Isso agora está disponível como comando instalável do PyPI, veja o final deste post.

Eu não sei de nenhum utilitário "padrão" que o faça, mas quando eu precisei dessa funcionalidade eu escrevi o seguinte script Python para ir de ZIP para arquivos compactados tar do 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)

Basta salvá-lo em zip2tar e torná-lo executável ou salvá-lo em zip2tar.py e executar python zip2tar.py . Forneça o nome do arquivo ZIP como um argumento para o script, o nome do arquivo de saída para xyz.zip será xyz.tar.bz2 .

A saída compactada do Bzip2 é normalmente muito menor que o arquivo zip, porque o último não usa padrões de compressã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 quiser que a saída seja compactada, remova :bz2 e .bz2 do código.

Se você tiver pip instalado em um ambiente python3, poderá fazer:

pip3 install ruamel.zip2tar

para obter um utilitário de linha de comando zip2tar fazendo o acima (disclaimer: Eu sou o autor desse pacote).

    
por 24.07.2014 / 08:07
5

O comando tar lida com sistemas de arquivos. Sua entrada é uma lista de arquivos que ele lê em um sistema de arquivos (incluindo muitos metadados). Você precisaria apresentar o arquivo zip como um sistema de arquivos para o comando tar para lê-lo.

Um Virtual File System - AVFS permitirá que qualquer programa veja dentro de arquivos compactados ou compactados através de uma interface de sistema de arquivos padrão via FUSE .

Há algumas informações detalhadas em o arquivo avfs-fuse readme e algumas distribuições tem pacotes para isso.

Um que você tenha o AVFS instalado, então você pode

mountavfs
cd ~/.avfs/path/to/somefile.zip#
tar -cvf /path/whatever.tar .

O AVFS preencherá todas as informações do sistema de arquivos que estiverem faltando no zip, como a propriedade do arquivo, que o tar selecionará.

    
por 24.07.2014 / 08:54
0

Veja um pequeno snippet que converte um arquivo ZIP em um arquivo TAR.GZ correspondente OnTheFly.

Converte o arquivo ZIP no arquivo TAR imediatamente

# 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)

Fonte

    
por 05.07.2015 / 15:37