C'è un modo per convertire uno zip in un tar senza estrarlo nel filesystem?


17

C'è un modo per convertire un ziparchivio in un tararchivio senza estrarlo prima in una directory temporanea? (e senza scrivere la mia implementazione di taro unzip)


Conti montare l'archivio zip come estrarlo nel filesystem? Se sì, allora puoi farlo senza estrarre nulla con libarchive ma ciò implica la codifica.
Celada,

Penso che l' operazione cerchi qualcosa come questo superuser.com/questions/325504/… è il tipo di cosa che speri di ottenere?
vfbsilva,

Risposte:


12

Questo è ora disponibile come comando installabile da PyPI, vedere la fine di questo post.


Non conosco alcuna utility "standard" che lo faccia, ma quando avevo bisogno di questa funzionalità ho scritto il seguente script Python per passare dagli archivi tar compressi ZIP a Bzip2 senza estrarre prima nulla sul disco:

#! /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 salvarlo zip2tare renderlo eseguibile o salvarlo zip2tar.pyed eseguirlo python zip2tar.py. Fornire il nome del file ZIP come argomento per lo script, il nome del file di output per xyz.zipsarà xyz.tar.bz2.

L'output compresso di Bzip2 è normalmente molto più piccolo del file zip perché quest'ultimo non utilizza schemi di compressione su più file, ma c'è anche meno possibilità di recuperare il file successivo se qualcosa nel file Bzip2 è sbagliato.

Se non si desidera comprimere l'output, rimuovere :bz2e .bz2dal codice.


Se hai pipinstallato in un ambiente python3, puoi fare:

pip3 install ruamel.zip2tar

per ottenere zip2tarun'utilità da riga di comando che fa quanto sopra (dichiarazione di non responsabilità: sono l'autore di quel pacchetto).


1
Ben fatto. Sembra che lo script non tenti di copiare metadati come il tempo di modifica del file e le autorizzazioni attraverso la modifica del formato di archivio, ma penso che potresti aggiungerlo abbastanza facilmente.
Celada,

@Celada Ho aggiunto il tempo di modifica del file (perso che durante la copia e incolla dal mio codice originale), non sono sicuro che lo standard ZIP disponga effettivamente delle autorizzazioni, AFAIK (moderno) tar è più completo a tale riguardo con ZIP più orientato a Windows .
Anthon,

Esattamente quello che stavo cercando. Mi aspettavo che un'utilità come questa fosse disponibile dai pacchetti unix standard. Qual è la licenza di questo? Vorrei proporlo per essere incluso in alcuni pacchetti (ad esempio, i devutils di Debian), forse dopo alcune generalizzazioni.
rbrito,

Un altro commento: il riferimento a timemanca un import.
rbrito,

@rbrito Lo posterò su PyPI, qualsiasi distro può prenderlo da lì. Proprio come alcuni fanno con il mio pacchetto ruamel.yaml. Grazie per il timecommento, aggiorno la risposta
Anthon,

5

Il tarcomando si occupa dei file system. Il suo input è un elenco di file che poi legge da un file system (inclusi molti metadati). Dovresti presentare il file zip come file system affinché il tarcomando lo legga.

Un file system virtuale - AVFS consentirà a qualsiasi programma di guardare all'interno di file archiviati o compressi tramite un'interfaccia di file system standard tramite FUSE .

Ci sono alcune informazioni dettagliate nel file Leggimi avfs-fuse e alcune distribuzioni hanno pacchetti per questo.

Uno su cui hai installato AVFS, quindi puoi farlo

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

AVFS inserirà tutte le informazioni per il file system mancanti dallo zip, come la proprietà dei file, che tar raccoglierà.


0

Ecco un piccolo frammento che converte un archivio ZIP in un corrispondente archivio TAR.GZ OnTheFly.

Converti l'archivio ZIP in archivio TAR al volo

# 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.