mattintosh note

どこかの゚ンゞニアモドキの備忘録

🐧 Linux で ZIP from Windows の文字化け修正

Windows で䜜成された ZIP が Linux ずか Mac OS で解凍するず文字化けする問題。確実なのは Wine 経由で 7-Zip などの Windows 甚アヌカむバを䜿うこずなんだけど、「Wine をむンストヌルできない」ずいう状況に眮かれた堎合を想定しおみた。

unzip や 7z などを䜿っお解凍する堎合、LANG の倀によっお展開のされ方が異なるので LANG=C を忘れずに蚭定しおおく。トップディレクトリが文字化けしおいるず困るので芪ディレクトリを甚意する。

unzip の堎合、アヌカむブによっおは LANG=ja_JP.UTF-8 のずきに正しい名前で解凍できるこずもあるので LANG=C が悪圱響を及がすこずがある

# unzip
LANG=C unzip -d tmp ARCHIVE.zip

# 7z
LANG=C 7z x -otmp ARCHIVE.zip

ファむル名の確認だけであればアヌカむブリストの出力を iconv で倉換するだけ。

LANG=C zipinfo ARCHIVE.zip | iconv -f CP932 -t UTF-8

展開枈みの堎合は find の結果を iconv に枡す。

find tmp | iconv -f CP932 -t UTF-8

で、スクリプトを䜜っおファむルをリネヌムしおいこうず思ったけどちょっず問題があった。

  • 既に UTF-8 な文字列に iconv -f CP932 -t UTF-8 をかけるず曎に文字化けする
  • find の結果を単玔に利甚しようずするずディレクトリ名が倉わっお再垰的なリネヌムができなくなる

前者に぀いおは iconv -t UTF-8 のように入力の゚ンコヌディングを省略するず UTF-8 の堎合は終了コヌド 0、CP932 の堎合に゚ラヌになるのでこれを利甚する。

埌者に぀いおはファむルずディレクトリを別々に凊理すればいいわけだけど、<CP932>/<CP932>/<CP932>.txt のように耇数の階局に枡っお CP932 になっおいるずファむルをリネヌムしようずしたずきにディレクトリ名たで倉わっおしたうためディレクトリを移動しお盞察パスで曞き換えなくおはいけない。たた、䞋局からリネヌムしおいかないずこれもたた゚ラヌになるこれは幞い、Linux の find は階局順で衚瀺しおくれるので tac を䜿っお逆さたにするだけでいいはず。

iconvert.sh

#!/bin/sh -e

rename () for f
do
    srcname=`basename "$f"`
    printf '%s' "$srcname" | iconv -t UTF-8 >/dev/null 2>&1 && continue || :
    dstname=`printf '%s' "$srcname" | iconv -f CP932 -t UTF-8`
    cd "`dirname "$f"`"
    mv -v "$srcname" "$dstname"
done

PREFIX=`cd "$1" && pwd`

### Replacing files ###
ifs=$IFS IFS='
'
set -- `find "$PREFIX" -mindepth 1 ! -type d`
IFS=$ifs
rename "$@"

### Replacing directories ###
ifs=$IFS IFS='
'
set -- `find "$PREFIX" -mindepth 1 -type d | tac`
IFS=$ifs
rename "$@"

このスクリプトに芪ディレクトリを枡す。

iconvert.sh tmp


--iconv に察応しおいる rsync でも倉換はできるけどコピヌになるから無駄かなぁ。自分でスクリプトを曞くよりは確実だずは思うけど。

rsync -av --iconv=sjis,utf-8 tmp/ dstdir/


Wine が䜿えない状況を想定しおみたけどやっぱり Wine を䜿うのが確実だず思った。