Windows에서 올바른 파일 이름을 갖도록 Linux에서 zip / tgz를 어떻게 만들 수 있습니까?


26

현재 tar -zcf arch.tgz files/*파일 이름은 UTF로 인코딩되므로 Windows 사용자는 파일 이름에 버릇 이없는 영어 문자 가 아닌 모든 문자를 볼 수 있으며 아무 것도 할 수 없습니다.

zip -qq -r arch.zip files/* 같은 행동을합니다.

Windows 사용자가 압축을 풀 때 모든 파일 이름이 올바르게 인코딩되도록 zip / tgz 아카이브를 어떻게 만들 수 있습니까?

답변:


24

현재 tar는 파일 이름을 UTF로 인코딩합니다

실제로 tar는 파일 이름을 전혀 인코딩 / 디코딩하지 않으며 파일 시스템에서 그대로 그대로 복사합니다. 로케일이 UTF-8 기반 인 경우 (많은 최신 Linux 배포판에서와 같이) UTF-8이됩니다. 불행히도 Windows 상자의 시스템 코드 페이지는 UTF-8이 아니므로 WinRAR과 같은 도구를 사용하여 문자 집합을 변경할 수있는 경우를 제외하고 이름이 항상 엉망이됩니다.

따라서 다른 국가의 Windows 릴리스 및 기본 제공 압축 폴더 지원에서 작동하는 비 ASCII 파일 이름으로 ZIP 파일을 만들 수 없습니다.

고정 또는 제공된 인코딩 정보가없는 tar 및 zip 형식의 단점이므로 ASCII가 아닌 문자는 항상 이식 할 수 없습니다. 비 ASCII 아카이브 형식이 필요한 경우 최근 7z 또는 rar와 같은 최신 형식 중 하나를 사용해야합니다. 불행히도 이것들은 여전히 ​​엉뚱합니다. 7zip에서는 -mcu스위치 가 필요 하며 rar는 코드 페이지에없는 문자를 감지하지 않으면 UTF-8을 사용하지 않습니다.

기본적으로 그것은 끔찍한 혼란이며 ASCII가 아닌 문자로 파일 이름이 포함 된 아카이브를 배포하는 것을 피할 수 있다면 훨씬 나을 것입니다.


감사합니다! 불행히도, 대부분의 사용자는 7z에 대해 전혀 모른다. 그리고 rar은 독점적이다 :(
kolypto

그래, 문제 야 ZIP은 모든 최신 OS가 기본 UI를 지원하므로 사용자에게 가장 유용한 솔루션입니다. 불행히도 오늘날 charset 문제는 ​​실제로 ZIP으로 해결할 수 없으며 다른 아카이브 형식에서도 여전히 문제가됩니다.
bobince

25

다음은 Windows의 UNIX에서 tar 파일의 압축을 풀기 위해 작성한 간단한 Python 스크립트입니다.

import tarfile

archive_name = "archive_name.tar"

def recover(name):
    return unicode(name, 'utf-8')

tar = tarfile.open(name=archive_name, mode='r', bufsize=16*1024)
updated = []
for m in tar.getmembers():
    m.name = recover(m.name)
    updated.append(m)

tar.extractall(members=updated)
tar.close()

대박! 이 스크립트는 구 Solaris 서버에서 작성된 EUC-JP 인코딩 tar 파일을 변환하는 데 도움이되었습니다.
wm_eddie

선생님, 당신은 내 생명을 구했습니다. 신의 축복이 있기를 :)
user1576772

8

리눅스에서 기본 tar(GNU tar)을 사용하는 문제 는 해결됩니다 ... --format=posix파일을 만들 때 매개 변수를 추가 하십시오.

예를 들면 다음과 같습니다.
tar --format=posix -cf

Windows에서는 파일을 추출하기 위해 bsdtar를 사용 합니다 .

에서 https://lists.gnu.org/archive/html/bug-tar/2005-02/msg00018.html 는 (이후 기록 된 2005 !)

> UTF-8이 지원되는 것에 대해 ChangeLog에서 무언가를 읽었습니다. 무엇을
의미합니까?
>
서로 다른 로케일간에 교환 가능한 아카이브를 작성할 수있는 방법을 찾지 못했습니다 .

POSIX.1-2001 형식 (tar --format = posix 또는 --format = pax)으로 아카이브를 작성할 때 tar는 파일 이름을 현재 로케일에서 UTF-8로 변환 한 다음 아카이브에 저장합니다. 추출 할 때는 역 동작이 수행됩니다.

PS 입력하는 대신을 입력 --format=posix할 수 있습니다 -H pax.


5

Zip 컨테이너 형식 자체에 문제가 있다고 생각합니다. 타르도 같은 문제로 고통 받고 있습니다.

대신 7zip ( .7z) 또는 RAR ( .rar) 아카이브 형식을 사용하십시오. 둘 다 Windows 및 Linux에서 사용 가능합니다. p7zip소프트웨어는 두 형식을 모두 처리합니다.

난 그냥 만들기 테스트 .7z, .rar, .zip, 및 .tarWINXP 데비안 (5), 그리고 모두의 파일 .7z.rar그동안 파일 저장소 / 제대로 파일 이름 복원 .zip.tar파일을하지 않습니다. 테스트 아카이브를 작성하는 데 사용되는 시스템은 중요하지 않습니다.


5

Windows 사용자로부터받은 압축 풀기 tarzip파일에 문제가있었습니다 . 내가 질문에 대답하지 않지만, 압축 풀기에 도움 아래의 스크립트 "어떻게 작동 아카이브 만들기" tarzip제대로 관계없이 파일을 원래의 OS를.

WARNING 하나는 조정 (소스 수동 코딩 가지고 cp1251, cp866아래의 실시 예 참조). 명령 줄 옵션은 향후 좋은 솔루션이 될 수 있습니다.

타르:

#!/usr/bin/env python

import tarfile
import codecs
import sys

def recover(name):
    return codecs.decode(name, 'cp1251')

for tar_filename in sys.argv[1:]:
    tar = tarfile.open(name=tar_filename, mode='r', bufsize=16*1024)
    updated = []
    for m in tar.getmembers():
        m.name = recover(m.name)
        updated.append(m)
    tar.extractall(members=updated)
    tar.close()

지퍼:

#!/usr/bin/env python

import zipfile
import os
import codecs
import sys

def recover(name):
    return codecs.decode(name, 'cp866')

for filename in sys.argv[1:]:
    archive = zipfile.ZipFile(filename, 'r')
    infolist = archive.infolist()
    for i in infolist:
        f = recover(i.filename)
        print f
        if f.endswith("/"):
            os.makedirs(os.path.dirname(f))
        else:
            open(f, 'w').write(archive.read(i))
    archive.close()

UPD 2018-01-02 : chardet패키지를 사용 하여 원시 데이터 청크의 올바른 인코딩을 추측합니다. 이제 스크립트는 모든 나쁜 아카이브뿐만 아니라 좋은 아카이브에서도 즉시 작동합니다.

참고 사항 :

  1. 모든 파일 이름이 추출되어 단일 문자열로 병합되어 인코딩 추측 엔진의 텍스트를 더 크게 만듭니다. 그것은 서로 다른 방식으로 조여진 파일 이름이 거의 없다는 것을 의미합니다.
  2. 좋은 유니 코드 텍스트를 처리하기 위해 특수 빠른 경로가 사용되었습니다 ( chardet일반 유니 코드 객체에서는 작동하지 않음).
  3. Doctest가 추가되어 노멀 라이저가 합리적으로 짧은 문자열에서 인코딩을 인식 함을 보여줍니다.

최종 버전 :

#!/usr/bin/env python2
# coding=utf-8

import zipfile
import os
import codecs
import sys

import chardet


def make_encoding_normalizer(txt):
    u'''
    Takes raw data and returns function to normalize encoding of the data.
        * `txt` is either unicode or raw bytes;
        * `chardet` library is used to guess the correct encoding.

    >>> n_unicode = make_encoding_normalizer(u"Привет!")
    >>> print n_unicode(u"День добрый")
    День добрый

    >>> n_cp1251 = make_encoding_normalizer(u"Привет!".encode('cp1251'))
    >>> print n_cp1251(u"День добрый".encode('cp1251'))
    День добрый
    >>> type(n_cp1251(u"День добрый".encode('cp1251')))
    <type 'unicode'>
    '''
    if isinstance(txt, unicode):
        return lambda text: text

    enc = chardet.detect(txt)['encoding']
    return lambda file_name: codecs.decode(file_name, enc)


for filename in sys.argv[1:]:
    archive = zipfile.ZipFile(filename, 'r')
    infolist = archive.infolist()

    probe_txt = "\n".join(i.filename for i in infolist)
    normalizer = make_encoding_normalizer(probe_txt)

    for i in infolist:
        print i.filename
        f = normalizer(i.filename)
        print f
        dirname = os.path.dirname(f)
        if dirname:
            assert os.path.abspath(dirname).startswith(os.path.abspath(".")), \
                "Security violation"
            if not os.path.exists(dirname):
                os.makedirs(dirname)
        if not f.endswith("/"):
            open(f, 'w').write(archive.read(i))
    archive.close()


if __name__ == '__main__' and len(sys.argv) == 1:
    # Hack for Python 2.x to support unicode source files as doctest sources.
    reload(sys)
    sys.setdefaultencoding("UTF-8")

    import doctest
    doctest.testmod()

    print "If there are no messages above, the script passes all tests."

당신의 프로그램에 감사드립니다! 유감스럽게도 Zip 프로그램은 Python 3에서는 작동하지 않지만 Python 2에서는 작동합니다.
beroal

@beroal, 스크립트를 업데이트했습니다. 이제 Mozilla 용 Firefox에서 개발 한 엔진을 사용하여 인코딩을 자동 감지합니다.
dmitry_romanov

4

POSIX-1.2001은 TAR이 UTF-8을 사용하는 방법을 지정했습니다.

2007 년 현재 PKZIP APPNOTE.TXT ( http://www.pkware.com/documents/casestudies/APPNOTE.TXT ) 의 changelog 버전 6.3.0은 ZIP에서 UTF-8을 사용하는 방법을 지정했습니다.

이러한 표준을 올바르게 지원하는 도구는 무엇입니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.