Gibt es eine Möglichkeit, eine Zip-Datei in eine Teer-Datei umzuwandeln, ohne sie in das Dateisystem zu extrahieren?


17

Gibt es eine Möglichkeit, ein zipArchiv in ein tarArchiv zu konvertieren , ohne es zuerst in ein temporäres Verzeichnis zu extrahieren? (und ohne meine eigene Implementierung von taroder zu schreiben unzip)


Zählen Sie das Mounten des Zip-Archivs zum Extrahieren in das Dateisystem? Wenn ja, dann können Sie es tun, ohne etwas mit libarchive zu extrahieren, aber das beinhaltet Codierung.
— Celada

Ich denke, die Operation sieht nach so etwas aus. Superuser.com/questions/325504/… ist es das, was Sie sich erhoffen?
— Vfbsilva

Antworten:


12

Dies ist jetzt als installierbarer Befehl von PyPI verfügbar (siehe Ende dieses Beitrags).


Ich kenne kein "Standard" -Dienstprogramm, das dies tut, aber als ich diese Funktionalität benötigte, schrieb ich das folgende Python-Skript, um von ZIP zu Bzip2-komprimierten Tar-Archiven zu wechseln, ohne zuerst etwas auf die Festplatte zu extrahieren:

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

Einfach speichern zip2tarund ausführbar machen oder speichern zip2tar.pyund ausführen python zip2tar.py. Geben Sie den ZIP-Dateinamen als Argument für das Skript an. Der Ausgabedateiname für xyz.ziplautet xyz.tar.bz2.

Die komprimierte Ausgabe von Bzip2 ist normalerweise viel kleiner als die ZIP-Datei, da letztere keine Komprimierungsmuster für mehrere Dateien verwendet, aber es besteht auch eine geringere Wahrscheinlichkeit, dass eine spätere Datei wiederhergestellt wird, wenn etwas in der Bzip2-Datei nicht stimmt.

Wenn Sie die Ausgabe nicht komprimieren möchten, entfernen Sie :bz2und .bz2aus dem Code.


Wenn Sie pipin einer python3-Umgebung installiert haben , können Sie Folgendes tun:

pip3 install ruamel.zip2tar

Um ein zip2tarKommandozeilen-Dienstprogramm zu erhalten, das die oben genannten Schritte ausführt (Haftungsausschluss: Ich bin der Autor dieses Pakets).


1
Schön. Es sieht so aus, als würde das Skript nicht versuchen, Metadaten wie Änderungszeit und Berechtigungen für das Archivformat zu kopieren, aber ich denke, Sie könnten das ganz einfach hinzufügen.
— Celada

@ Celada Ich habe die Änderungszeit für Dateien hinzugefügt (da ich beim Kopieren und Einfügen aus meinem Originalcode nicht weiß, ob der ZIP-Standard tatsächlich Berechtigungen hat). AFAIK (modern) tar ist in dieser Hinsicht vollständiger, da ZIP mehr auf Windows ausgerichtet ist .
— Anthon

Genau das, wonach ich gesucht habe. Ich habe erwartet, dass ein solches Dienstprogramm in Standard-Unix-Paketen verfügbar sein wird. Was ist die Lizenz dafür? Ich möchte vorschlagen, dass es in einigen Paketen (z. B. Debians Devutils) enthalten ist, möglicherweise nach einigen Verallgemeinerungen.
— Großbritannien

Noch ein Kommentar: Dem Verweis auf timefehlt ein import.
— Großbritannien

@rbrito Ich werde das auf PyPI posten, jede Distribution kann es von dort abholen. Genau wie manche mit meinem ruamel.yaml-Paket machen. Vielen Dank für den timeKommentar, ich aktualisiere die Antwort
— Anthon

5

Der tarBefehl behandelt Dateisysteme. Die Eingabe ist eine Liste von Dateien, die dann aus einem Dateisystem gelesen werden (einschließlich vieler Metadaten). Sie müssten die zip-Datei als Dateisystem präsentieren, damit der tarBefehl sie lesen kann.

Ein virtuelles Dateisystem - Mit AVFS kann jedes Programm über eine standardmäßige Dateisystemschnittstelle über FUSE in archivierte oder komprimierte Dateien schauen .

Es gibt einige detaillierte Informationen in der Readme-Datei von avfs-fuse und einige Distributionen haben Pakete dafür.

Wenn Sie AVFS installiert haben, können Sie

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

AVFS fügt alle Informationen für das Dateisystem ein, die in der ZIP-Datei fehlen, wie z. B. der Dateibesitz, den tar abholt.


0

Hier ist ein kleiner Ausschnitt, der ein ZIP-Archiv in ein passendes TAR.GZ-Archiv OnTheFly konvertiert.

Konvertieren Sie ZIP-Archiv in TAR-Archiv im laufenden Betrieb

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

Quelle

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.