답변:
현재 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가 아닌 문자로 파일 이름이 포함 된 아카이브를 배포하는 것을 피할 수 있다면 훨씬 나을 것입니다.
다음은 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()
리눅스에서 기본 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
.
Zip 컨테이너 형식 자체에 문제가 있다고 생각합니다. 타르도 같은 문제로 고통 받고 있습니다.
대신 7zip ( .7z
) 또는 RAR ( .rar
) 아카이브 형식을 사용하십시오. 둘 다 Windows 및 Linux에서 사용 가능합니다. p7zip
소프트웨어는 두 형식을 모두 처리합니다.
난 그냥 만들기 테스트 .7z
, .rar
, .zip
, 및 .tar
WINXP 데비안 (5), 그리고 모두의 파일 .7z
과 .rar
그동안 파일 저장소 / 제대로 파일 이름 복원 .zip
및 .tar
파일을하지 않습니다. 테스트 아카이브를 작성하는 데 사용되는 시스템은 중요하지 않습니다.
Windows 사용자로부터받은 압축 풀기 tar
와 zip
파일에 문제가있었습니다 . 내가 질문에 대답하지 않지만, 압축 풀기에 도움 아래의 스크립트 "어떻게 작동 아카이브 만들기" tar
와 zip
제대로 관계없이 파일을 원래의 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
패키지를 사용 하여 원시 데이터 청크의 올바른 인코딩을 추측합니다. 이제 스크립트는 모든 나쁜 아카이브뿐만 아니라 좋은 아카이브에서도 즉시 작동합니다.
참고 사항 :
chardet
일반 유니 코드 객체에서는 작동하지 않음).최종 버전 :
#!/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."
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을 사용하는 방법을 지정했습니다.
이러한 표준을 올바르게 지원하는 도구는 무엇입니까?