파일 시스템에서 사용되는 것과 다른 문자 인코딩을 사용하여 파일 이름을 압축 해제합니다.

파일 시스템에서 사용되는 것과 다른 문자 인코딩을 사용하여 파일 이름을 압축 해제합니다.

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}')

관련 정보