파일 시스템으로 압축을 풀지 않고 zip을 tar로 변환하는 방법이 있습니까?


17

임시 디렉토리로 먼저 추출하지 않고 zip아카이브를 아카이브 로 변환하는 방법이 tar있습니까? (그리고 내 자신의 구현을 작성하지 않고도 tar또는 unzip)


zip 아카이브 를 파일 시스템으로 추출하는 것으로 마운트 합니까? 그렇다면 libarchive로 아무것도 추출하지 않고 수행 할 수 있지만 코딩이 필요합니다.
Celada

나는 op 가이 superuser.com/questions/325504 / ... 와 같은 것을 찾는다고 생각합니다 .
vfbsilva

답변:


12

이제 PyPI에서 설치 가능한 명령으로 사용할 수 있습니다.이 게시물의 끝 부분을 참조하십시오.


나는 그렇게하는 "표준"유틸리티를 모르지만,이 기능이 필요할 때 먼저 디스크에 아무것도 추출하지 않고 ZIP에서 Bzip2 압축 tar 아카이브로 이동하기 위해 다음 Python 스크립트를 작성했습니다.

#! /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코드에서합니다.


pippython3 환경에 설치 한 경우 다음을 수행 할 수 있습니다.

pip3 install ruamel.zip2tar

zip2tar위의 작업을 수행 하는 명령 줄 유틸리티 를 얻습니다 (면책 조항 : 해당 패키지의 저자입니다).


1
좋은데 스크립트가 파일 수정 시간 및 아카이브 형식 변경에 대한 권한과 같은 메타 데이터를 복사하려고 시도하지 않는 것처럼 보이지만, 쉽게 추가 할 수 있다고 생각합니다.
Celada

@Celada 파일 수정 시간을 추가했습니다 (원본 코드에서 복사하여 붙여 넣는 동안 놓쳤습니다) .ZIP 표준에 실제로 권한이 있는지 확실하지 않습니다 .AFAIK (현대) tar는 Windows보다 ZIP에 더 적합합니다. .
Anthon

정확히 내가 찾던 것. 표준 유닉스 패키지에서 이와 같은 유틸리티를 사용할 수있을 것으로 기대했습니다. 이것의 라이센스는 무엇입니까? 아마도 일부 일반화 후에 일부 패키지 (예 : 데비안 devutils)에 포함되도록 제안하고 싶습니다.
rbrito

또 다른 의견 :에 대한 참조가 time부족합니다 import.
rbrito

@ rbrito 나는 이것을 PyPI에 게시 할 것이고, 어떤 배포판에서도 그것을 가져올 수 있습니다. 내 ruamel.yaml 패키지를 사용하는 것과 마찬가지로. time의견 주셔서 감사합니다 , 나는 대답을 업데이트합니다
Anthon

5

tar명령은 파일 시스템을 처리합니다. 입력은 파일 시스템에서 읽은 파일 목록입니다 (많은 메타 데이터 포함). tar명령 이 파일 을 읽으 려면 zip 파일을 파일 시스템으로 제공해야 합니다.

가상 파일 시스템-AVFS 를 사용하면 모든 프로그램이 FUSE 를 통해 표준 파일 시스템 인터페이스를 통해 아카이브 또는 압축 파일 내부를 볼 수 있습니다 .

avfs-fuse 추가 정보에 자세한 정보가 있으며 일부 배포판 에는 패키지 가 있습니다.

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.