Чи є спосіб перетворити zip в tar, не вилучаючи його до файлової системи?


17

Чи є спосіб перетворити zipархів в tarархів, не спершу витягуючи його до тимчасового каталогу? (і без написання власної реалізації tarабо unzip)


Чи вважаєте ви встановлення zip-архіву витягом його до файлової системи? Якщо так, то ви можете зробити це без вилучення нічого з лібархією, але це включає кодування.
Селада

Я думаю, що ОП шукає щось подібне до цього superuser.com/questions/325504/… це та річ, яку ви сподіваєтеся досягти?
vfbsilva

Відповіді:


12

Тепер це доступно як інстальована команда від PyPI, дивіться в кінці цієї публікації.


Я не знаю жодної "стандартної" утиліти, яка це робить, але коли мені знадобилася ця функціональність, я написав наступний скрипт Python, щоб перейти від ZIP до архівів стислих смол Bzip2, не виймаючи спочатку нічого на диск:

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

Просто збережіть його zip2tarта зробіть його виконуваним або збережіть у zip2tar.pyта запустіть python zip2tar.py. Надайте ім'я ZIP-файлу як аргумент сценарію, вихідне ім'я файлу xyz.zipбуде xyz.tar.bz2.

Стислий вихід Bzip2 зазвичай набагато менший, ніж zip-файл, оскільки останній не використовує шаблони стиснення для декількох файлів, але також є менший шанс відновити пізніший файл, якщо щось у файлі Bzip2 неправильно.

Якщо ви не хочете, щоб вихід був стислий, видаліть :bz2і .bz2з коду.


Якщо ви pipвстановлені в середовищі python3, ви можете:

pip3 install ruamel.zip2tar

щоб отримати zip2tarутиліту командного рядка, виконуючи вказане вище (відмова від відповідальності: я автор цього пакета).


1
Хороший. Схоже, сценарій не робить жодних спроб скопіювати метадані, такі як час модифікації файлів та дозволи в межах зміни формату архіву, але я думаю, ви могли це додати досить легко.
Селада

@Celada Я додав час модифікації файлу (пропустив, що при копіюванні та вставці з мого початкового коду), я не впевнений, що стандарт ZIP фактично має дозволи, AFAIK (сучасний) tar є більш повним в цьому відношенні, оскільки ZIP більше орієнтований на Windows .
Антон

Саме те, що я шукав. Я очікував, що одна така утиліта буде доступна зі стандартних пакетів Unix. Що це за ліцензія? Я хотів би запропонувати його включити до деяких пакунків (наприклад, девутилів Debian), можливо, після деяких узагальнень.
rbrito

Ще один коментар: посилання на timeнедолік має import.
rbrito

@rbrito Я опублікую це на PyPI, будь-який дистрибутив може забрати його звідти. Як і деякі з моїм пакетом ruamel.yaml. Дякую за timeкоментар, я оновлюю відповідь
Anthon

5

tarКоманда має справу з файловими системами. Його введення - це список файлів, який він потім читає з файлової системи (включаючи багато метаданих). Вам потрібно буде представити zip-файл як файлову систему для tarкоманди для його читання.

Віртуальна файлова система - AVFS дозволить будь-якій програмі заглядати всередину архівованих або стислих файлів через стандартний інтерфейс файлової системи через FUSE .

У readme avfs-fuse є деяка детальна інформація, а деякі дистрибутиви мають пакети для цього.

Один у вас встановлений AVFS, тоді ви можете

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

AVFS заповнить будь-яку інформацію для файлової системи, якої немає в zip, як, наприклад, право власності на файл, що тар підбере.


0

Ось невеликий фрагмент, який перетворює ZIP-архів у відповідний архів TAR.GZ OnTheFly.

Перетворіть ZIP-архів в архів TAR на льоту

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

Джерело

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.