มีวิธีแปลง zip เป็น tar โดยไม่ต้องแตกไฟล์ไปยังระบบไฟล์หรือไม่?


17

มีวิธีแปลงzipไฟล์เก็บถาวรเป็นtarไฟล์เก็บถาวรโดยไม่แยกไปที่ไดเรกทอรีชั่วคราวก่อนหรือไม่? (และโดยไม่ต้องเขียนการใช้งานของฉันเองtarหรือunzip)


คุณนับการเมานต์ไฟล์ zipในขณะที่แตกไปยังระบบไฟล์หรือไม่? ถ้าใช่คุณสามารถทำได้โดยไม่ต้องแยกสิ่งใดด้วยlibarchiveแต่เกี่ยวข้องกับการเข้ารหัส
Celada

ฉันคิดว่า op มองหาสิ่งที่คล้ายกับsuperuser.com/questions/325504//นี้เป็นสิ่งที่คุณคาดหวังหรือไม่
vfbsilva

คำตอบ:


12

ตอนนี้มีให้ใช้งานเป็นคำสั่งที่ติดตั้งได้จาก PyPI ดูที่ส่วนท้ายของโพสต์นี้


ฉันไม่ทราบว่ายูทิลิตี้ "มาตรฐาน" ใดที่ทำเช่นนั้น แต่เมื่อฉันต้องการฟังก์ชั่นนี้ฉันได้เขียนสคริปต์ Python ต่อไปนี้เพื่อไปจากไฟล์ ZIP ไปยัง Bzip2 บีบอัด tar โดยไม่ต้องแตกไฟล์ลงในดิสก์ก่อน:

#! /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ให้ชื่อไฟล์ไปรษณีย์เป็นอาร์กิวเมนต์สคริปต์ที่ชื่อไฟล์ผลลัพธ์สำหรับจะเป็นxyz.zipxyz.tar.bz2

โดยปกติแล้วเอาต์พุตบีบอัด Bzip2 นั้นเล็กกว่าไฟล์ zip มากเพราะไฟล์หลังไม่ได้ใช้รูปแบบการบีบอัดมากกว่าหลายไฟล์ แต่ก็มีโอกาสน้อยกว่าในการกู้คืนไฟล์ในภายหลังหากมีบางสิ่งในไฟล์ Bzip2 ไม่ถูกต้อง

หากคุณไม่ต้องการให้เอาท์พุทที่ถูกบีบอัดเอาออก:bz2และ.bz2จากรหัส


หากคุณpipติดตั้งในสภาพแวดล้อม python3 คุณสามารถทำได้:

pip3 install ruamel.zip2tar

เพื่อรับzip2tarอรรถประโยชน์ commandline ทำข้างต้น (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนของแพคเกจนั้น)


1
ทำได้ดีนี่. ดูเหมือนว่าสคริปต์จะไม่พยายามคัดลอกข้อมูลเมตาเช่นเวลาแก้ไขไฟล์และการอนุญาตในการเปลี่ยนรูปแบบไฟล์เก็บถาวร แต่ฉันคิดว่าคุณสามารถเพิ่มได้อย่างง่ายดาย
Celada

@Celada ฉันเพิ่มเวลาในการแก้ไขไฟล์ (พลาดในขณะที่คัดลอกและวางจากรหัสเดิมของฉัน) ฉันไม่แน่ใจว่ามาตรฐาน ZIP มีสิทธิ์จริงหรือไม่ AFAIK (modern) tar นั้นสมบูรณ์กว่าด้วย ZIP มากกว่าที่เป็น Windows .
Anthon

สิ่งที่ฉันกำลังมองหา ฉันคาดว่าหนึ่งยูทิลิตี้เช่นนี้จะสามารถใช้ได้จากแพ็คเกจ unix มาตรฐาน ใบอนุญาตนี้คืออะไร? ฉันต้องการเสนอให้รวมอยู่ในแพ็คเกจบางอย่าง (เช่นเดเบียนของเดเบียน) บางทีหลังจากผ่านการสรุปทั่วไป
rbrito

อีกความคิดเห็น: อ้างอิงถึงขาดtime import
rbrito

@rbrito ฉันจะโพสต์สิ่งนี้บน PyPI ผู้ใดก็ตามที่สามารถรับ distro ได้ เช่นเดียวกับที่ทำกับแพคเกจ ruamel.yaml ของฉัน ขอบคุณสำหรับtimeความคิดเห็นฉันอัปเดตคำตอบ
Anthon

5

tarข้อเสนอคำสั่งที่มีระบบไฟล์ อินพุตของมันคือรายการไฟล์ที่อ่านจากระบบไฟล์ (รวมถึงข้อมูลเมตาจำนวนมาก) คุณจะต้องแสดงไฟล์ zip เป็นระบบไฟล์เพื่อให้tarคำสั่งอ่าน

ไฟล์ระบบเสมือนจริง - AVFSจะช่วยให้โปรแกรมใด ๆ ที่จะดูไฟล์ที่เก็บไว้ภายในหรือบีบอัดผ่านทางอินเตอร์เฟซระบบไฟล์มาตรฐานผ่านFUSE

มีข้อมูลรายละเอียดบางอย่างในavfs-fuse readmeและการแจกแจง บางอย่างมี แพ็คเกจสำหรับมัน

อันที่คุณมี AVFS ติดตั้งแล้วคุณสามารถ

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

AVFS จะกรอกข้อมูลใด ๆ สำหรับระบบไฟล์ที่หายไปจาก zip เช่นความเป็นเจ้าของไฟล์ tar ที่จะรับ


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)

แหล่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.