ISO-8859-1이나 기타 유니코드 이전 구성표로 인코딩된 파일 이름이 포함된 타르볼을 가끔 받습니다. 내 시스템은 UTF-8을 사용하므로 tar xvf foo.tar
일반적인 옵션()을 사용하여 이러한 아카이브의 압축을 풀면 mojibake 파일 이름으로 가득 찬 디렉터리가 생성됩니다.
지금까지 나는 사용해왔다.convmv
파일 이름을 UTF-8로 변환뒤쪽에그들은 추출되었습니다. 영향을 받은 각 파일을 호출하거나 convmv
파일의 압축을 새 디렉터리에 convmv
풀고 전체 디렉터리에서 실행한 다음 원래 원했던 위치로 파일을 이동해야 하기 때문에 이는 약간 불편합니다. 이 기능을 쉘 스크립트로 인코딩할 수 없는 경우 압축을 풀 때 아카이브 파일 이름을 즉시 UTF-8로 변환할 수 있는 방법이 있습니까?
답변1
tar
이것은 추출하기 전에 메모리의 이름을 수정하는 작은 파일 추출기입니다 .
#!/usr/bin/python27
import tarfile
def transform(data):
u = data.decode('latin1')
return u.encode('utf8')
tar = tarfile.open('archive.tar')
for m in tar.getmembers():
m.name = transform(m.name)
tar.extractall()
경고하다:GNU와 달리 tar
이 추출기는 선행 문자를 제거하지 않습니다 /
. 이 추출기에 검사 논리를 tar
추가 하거나 tar -t
.
답변2
토마스 에커의 답변호출이 getmembers
전체 아카이브를 메모리로 읽는 것처럼 보이고 내가 가지고 있는 tar 파일이 너무 크다는 점을 제외하면 거의 작동합니다. 수정된 버전의 파일을 한 번에 하나씩 읽습니다. 내 tar 파일에서 파일 이름에 대리 문자가 있는 것처럼 보이기 때문에 이름 변환도 다릅니다. 이것이 보편적으로 적용 가능한지는 확실하지 않습니다.
#!/usr/bin/env python3
import tarfile
import sys
from pathlib import Path
def transform(data):
try:
data.encode('utf-8')
return data
except UnicodeEncodeError as err:
u = data.encode('utf-8', 'surrogateescape')
v = u.decode('latin-1')
print(f'Replaced filename: {v}')
v.encode('utf-8') # check that it can be encoded
return v
tar = tarfile.open(sys.argv[1])
while (m := tar.next()) is not None:
if m.name == '.':
continue
m.name = transform(m.name)
path = Path(m.name)
try:
if path.stat().st_size == m.size:
print(f'Already exists with the same size: skipping {m.name}')
continue
else:
print(f'Size mismatch, extracting: {m.name}', flush=True)
except FileNotFoundError:
print(f'About to extract {m.name}', flush=True)
tar.extract(m)
print(f'Extracted {m.name}')