Czy istnieje sposób na konwersję zip do tar bez rozpakowywania go do systemu plików?

17

Czy istnieje sposób na konwersję ziparchiwum do tararchiwum bez rozpakowywania go najpierw do katalogu tymczasowego? (i bez pisania własnej implementacji tarlub unzip)

użytkownik253751
źródło
Czy liczycie montowanie archiwum zip jako rozpakowywanie go do systemu plików? Jeśli tak, możesz to zrobić bez rozpakowywania czegokolwiek przy pomocy libarchive, ale wymaga to kodowania.
Celada
Myślę, że op szuka czegoś takiego jak ten superuser.com/questions/325504/... czy jest to coś, co masz nadzieję osiągnąć?
vfbsilva

Odpowiedzi:

12

To jest teraz dostępne jako polecenie instalacyjne z PyPI, patrz koniec tego postu.


Nie znam żadnego „standardowego” narzędzia, które to robi, ale kiedy potrzebowałem tej funkcji, napisałem następujący skrypt Pythona, aby przejść z archiwów tar skompresowanych do formatu Bzip2 bez rozpakowywania plików na dysk:

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

Po prostu zapisz go zip2tari zrób, aby był wykonywalny lub zapisz go zip2tar.pyi uruchom python zip2tar.py. Podaj nazwę pliku ZIP jako argument skryptu, a wyjściową nazwą pliku xyz.zipbędzie xyz.tar.bz2.

Skompresowane wyjście Bzip2 jest zwykle znacznie mniejsze niż plik zip, ponieważ ten drugi nie używa wzorców kompresji dla wielu plików, ale istnieje również mniejsze prawdopodobieństwo odzyskania późniejszego pliku, jeśli coś w pliku Bzip2 jest nieprawidłowe.

Jeśli nie chcesz wyjście kompresowane, zdjąć :bz2i .bz2od kodu.


Jeśli pipzainstalowałeś w środowisku python3, możesz:

pip3 install ruamel.zip2tar

aby uzyskać zip2tarnarzędzie wiersza polecenia, wykonujące powyższe czynności (wyłączenie odpowiedzialności: Jestem autorem tego pakietu).

Anthon
źródło
1
Niezłe. Wygląda na to, że skrypt nie próbuje kopiować metadanych, takich jak czas modyfikacji pliku i uprawnienia dla zmiany formatu archiwum, ale myślę, że można to dość łatwo dodać.
Celada
@Celada Dodałem czas modyfikacji pliku (przegapiłem to podczas kopiowania i wklejania z mojego oryginalnego kodu), nie jestem pewien, czy standard ZIP faktycznie ma uprawnienia, tar AFAIK (nowoczesny) jest bardziej kompletny pod tym względem, a ZIP jest bardziej zorientowany na Windows .
Anthon
Właśnie tego szukałem. Spodziewałem się, że jedno takie narzędzie będzie dostępne ze standardowych pakietów uniksowych. Jaka jest licencja na to? Chciałbym zaproponować włączenie go do niektórych pakietów (np. Devutils Debiana), być może po kilku generalizacjach.
rbrito
Kolejny komentarz: odniesienie do timebraków import.
rbrito
@rbrito Zamieszczę to na PyPI, każda dystrybucja może to stamtąd odebrać. Tak jak niektórzy robią z moim pakietem ruamel.yaml. Dzięki za timekomentarz, aktualizuję odpowiedź
Anthon
5

tarKomenda dotyczy systemów plików. Dane wejściowe to lista plików, które następnie odczytuje z systemu plików (w tym wiele metadanych). Aby tarkomenda mogła go odczytać, musisz przedstawić plik zip jako system plików .

Wirtualny system plików - AVFS pozwoli każdemu programowi zajrzeć do zarchiwizowanych lub skompresowanych plików za pośrednictwem standardowego interfejsu systemu plików za pomocą FUSE .

W pliku readme avfs-fuse znajduje się kilka szczegółowych informacji, a niektóre dystrybucje zawierają odpowiednie pakiety .

Jeśli masz zainstalowany system AVFS, możesz

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

System AVFS wypełni wszelkie informacje dotyczące systemu plików, których brakuje w pliku zip, takie jak prawo własności do pliku, które tar pobierze.

Matt
źródło
0

Oto mały fragment, który konwertuje archiwum ZIP do pasującego archiwum TAR.GZ OnTheFly.

Konwertuj archiwum ZIP do archiwum TAR w locie

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

Źródło

Evgeni Braverman
źródło