Apakah ada cara untuk mengubah zip menjadi tar tanpa mengekstraknya ke sistem file?

17

Apakah ada cara untuk mengonversi ziparsip ke tararsip tanpa mengekstraksi ke direktori sementara terlebih dahulu? (dan tanpa menulis implementasi saya sendiri taratau unzip)

pengguna253751
sumber
Apakah Anda menghitung pemasangan arsip zip sebagai mengekstraknya ke sistem file? Jika ya, maka Anda dapat melakukannya tanpa mengekstraksi apa pun dengan libarchive tetapi itu melibatkan pengkodean.
Celada
Saya pikir op mencari sesuatu seperti ini superuser.com/questions/325504/... apakah itu jenis hal yang ingin Anda capai?
vfbsilva

Jawaban:

12

Ini sekarang tersedia sebagai perintah yang dapat diinstal dari PyPI, lihat akhir posting ini.


Saya tidak tahu ada utilitas "standar" yang melakukannya, tetapi ketika saya membutuhkan fungsionalitas ini, saya menulis skrip Python berikut untuk beralih dari ZIP ke Bzip2 arsip tar terkompresi tanpa mengekstraksi apa pun ke disk terlebih dahulu:

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

Hanya menyimpannya zip2tardan membuatnya dapat dieksekusi atau menyimpannya zip2tar.pydan berjalan python zip2tar.py. Berikan nama file ZIP sebagai argumen untuk skrip, nama file output xyz.zipakan xyz.tar.bz2.

Output terkompresi Bzip2 biasanya jauh lebih kecil daripada file zip karena yang terakhir tidak menggunakan pola kompresi lebih dari beberapa file, tetapi ada juga lebih sedikit peluang untuk memulihkan file kemudian jika ada sesuatu dalam file Bzip2 yang salah.

Jika Anda tidak ingin output dikompresi, hapus :bz2dan .bz2dari kode.


Jika Anda telah pipmenginstal di lingkungan python3, Anda dapat melakukan:

pip3 install ruamel.zip2tar

untuk mendapatkan zip2tarutilitas commandline melakukan hal di atas (penafian: Saya adalah pembuat paket itu).

Anthon
sumber
1
Bagus Sepertinya skrip tidak berupaya menyalin metadata seperti waktu modifikasi file dan izin di seluruh perubahan format arsip, tapi saya pikir Anda bisa menambahkannya dengan mudah.
Celada
@Celada Saya menambahkan waktu modifikasi file (terlewatkan saat menyalin dan menempel dari kode asli saya), saya tidak yakin apakah standar ZIP benar-benar memiliki izin, AFAIK (modern) tar lebih lengkap dalam hal sehubungan dengan ZIP lebih berorientasi Windows .
Anthon
Persis apa yang saya cari. Saya berharap satu utilitas seperti ini tersedia dari paket unix standar. Apa lisensi dari ini? Saya ingin mengusulkan untuk dimasukkan dalam beberapa paket (mis., Devutils Debian), mungkin setelah beberapa generalisasi.
rbrito
Komentar lain: referensi untuk timekekurangan import.
rbrito
@rbrito Saya akan memposting ini di PyPI, setiap distro dapat mengambilnya dari sana. Sama seperti beberapa lakukan dengan paket ruamel.yaml saya. Terima kasih atas timekomentarnya, saya memperbarui jawabannya
Anthon
5

The tarperintah berhubungan dengan file sistem. Inputnya adalah daftar file yang kemudian dibaca dari sistem file (termasuk banyak metadata). Anda perlu mempresentasikan file zip sebagai sistem file agar tarperintah membacanya.

Sistem File Virtual - AVFS akan memungkinkan program apa pun untuk melihat ke dalam file yang diarsipkan atau dikompresi melalui antarmuka sistem file standar melalui FUSE .

Ada beberapa informasi terperinci dalam readfs-fuse readme dan beberapa distribusi memiliki paket untuk itu.

Satu Anda telah menginstal AVFS, maka Anda bisa

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

AVFS akan mengisi semua informasi untuk sistem file yang hilang dari zip, seperti kepemilikan file, tar yang akan dijemput.

Mat
sumber
0

Berikut cuplikan kecil yang mengonversi arsip ZIP menjadi arsip TAR.GZ yang sesuai OnTheFly.

Ubah arsip ZIP menjadi arsip TAR dengan cepat

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

Sumber

Evgeni Braverman
sumber