Linuxにおけるテキストファイルのエンコーディング変換の方法

Linuxテキストの文字コード変換で最初に求められるのはcommand暗記ではなく、何を正しい結果とするかの定義です。結論は「iconvは入力を標準出力へ変換するため、元ファイルと同じパスへ直接redirectしません。変換元・変換先を明示し、一時ファイルへ出力、終了コードと文字化け・行数を確認してから別名で採用します。」。変換元encodingを推測で決めず、配布元仕様とサンプル表示を照合することを確認し、表示、加工、変更を混同しない順序で進めます。

目次

変換前にencodingとlocaleを証拠化する

文字コード変換では、原本を別名で保全し、file –mimeの推定結果だけでなく、業務上重要な日本語や記号を含む数行を抽出して確認します。iconvの入力・出力文字コードを明示し、変換後はUTF-8として再判定したうえで、行数、SHA-256、代表文字の表示を照合します。

  • file -biとhexdumpの先頭でBOMや推定charsetを確認する
  • locale charmapで現在の端末encodingを記録する
  • iconv -lで実装が受け付けるencoding名を確認する
  • 正しい文字が分かる数行を配布元や利用者と照合する

iconvは必ず別fileへ出力する

判定材料を集める

file -bi -- input.txt
locale charmap
LC_ALL=C hexdump -C -- input.txt | head -n 4

fileのcharsetは推定であり確定情報ではありません。BOM、配布仕様、実際の日本語サンプルを組み合わせ、CP932とShift_JISの差も考慮します。

別ファイルへ変換

iconv -f CP932 -t UTF-8 -- input.txt > output.utf8.txt
printf 'exit=%s\n' "$?"

変換先を別名にすることで原本を保持します。同じファイルを入力と出力へ指定すると、shellがiconv実行前に出力側を切り詰めるため禁止です。

変換結果を検査

file -bi -- output.utf8.txt
wc -l -- input.txt output.utf8.txt
iconv -f UTF-8 -t UTF-8 -- output.utf8.txt >/dev/null

再変換の終了コードはUTF-8として不正なbyte列がないかの一つの検査です。改行数、代表行、アプリへの読み込みも確認し、文字の意味が保たれたことを判断します。

採用前に原本hashを残す

sha256sum -- input.txt output.utf8.txt
cp -p -- input.txt input.txt.before-encoding-change
mv -- output.utf8.txt input.txt

最後のmvは変更操作です。検査が合格し、利用プロセスがファイルを開いていない時間帯にだけ実行します。戻すときはbeforeファイルを元名へ戻します。

文字化けと変換不能byteを見分ける

iconvは表現できない文字や不正なbyte列に遭遇すると失敗し得ます。-cで問題文字を捨てれば処理が進んでも、氏名や識別子が変わるため業務データでは既定にしません。//TRANSLITも実装依存で原文と別文字になるので、利用者承認なしに使いません。UTF-8 BOMの要否、CRLFとLFは文字コードとは別の論点として確認します。

discard optionで欠落を隠さない

  • inputとoutputを同じredirect先にする
  • fileの推定だけで変換元を断定する
  • -cで変換不能文字を黙って捨てる
  • CP932を標準Shift_JISと同一視する
  • encoding変換と改行コード変換を同時に行う

原本を残したまま採否を決める

変換前ファイルは読み取り専用の保管場所または世代付きコピーに残します。個人情報を含むデータをオンライン変換サービスへ上げず、ローカルで処理します。バッチ変換は1件で検証した後、対象一覧と出力先を分離して行います。失敗時は生成途中の一時ファイルを採用せず、元ファイルのhashとバックアップhashが一致することを確認して戻します。利用アプリが読めない場合はサービス側の期待encodingを再確認します。

round-tripではなく受け側仕様で検証する

代表文字として漢字、半角カナ、波ダッシュ、丸数字、外字候補を含む行を選び、変換前後を正しいviewerで照合します。件数、行数、CSV列数、アプリ取込結果を記録し、再現用にiconvの版、locale、from/to名を残します。戻し試験もコピー上で行い、原本を保持できる手順にします。

byte数・行数・再decodeで変換結果を確定する

iconvはsource encodingを推測しないため、-fと-tを明示して別fileへ出力します。変換成功はstatus 0でも文字の意味まで保証しないので、invalid sequence時のnonzero status、変換前後の行数、代表文字、必要なら往復変換を合わせて判定します。

CP932 fixtureをUTF-8へ変換する

iconv -f CP932 -t UTF-8 -- input.txt > output.utf8.txt
rc=$?
printf 'iconv_status=%s bytes=%s\n' "$rc" "$(wc -c < output.utf8.txt)"

正常変換・空入力・不正sequenceを分類する

  • 再decode成功:iconvがstatus 0で完了し、UTF-8 validatorと代表文字の目視・byte照合を通る
  • 空file・変換不要:空fileは有効な0 byte出力になり得るため、入力0 byteを意図したケースか確認する
  • 不正byte・出力失敗:illegal input sequence、truncated multibyte、出力先disk不足はstderrとnonzero statusで候補を不採用にする

file -biはheuristicでありcharset確定手段ではありません。//IGNOREや//TRANSLITはdata欠落・置換を成功に見せるため、要件で許可した場合だけ欠落件数を記録して使います。

末尾byteが欠けたsampleを拒否できるか

printf '\202' > invalid.cp932
if iconv -f CP932 -t UTF-8 invalid.cp932 >/dev/null 2>iconv.err; then echo UNEXPECTED_OK; else printf 'expected_error=%s\n' "$?"; fi

ASCII、日本語、CRLF、emojiを含む正規sampleと、末尾byte欠落sampleを分けます。変換後をUTF-8として再読込し、line数・Unicode code point・sha256・stderrを一組で保存します。

fileの推定表示だけではencodingを確定できません。既知文字を含むfixture、iconvの終了status、変換後の再decodeを組み合わせ、欠落を許容しない条件で採否を決めます。

変換不能文字と改行差を別々のfixtureで判定する

CP932からUTF-8へ変換するfixtureは、ASCII、漢字、半角カナ、波ダッシュ、丸数字に加え、末尾byte欠落を別ファイルで用意します。正常系はiconvのstatus 0、UTF-8としての再decode、期待するcode point、line数を同時に確認します。不正系はnonzero statusとstderrを期待し、-cや//IGNOREで欠落を成功扱いしません。

CRLFからLFへの変更やBOMの除去はencoding変換とは別の差分です。採用判定ではbyte数だけで一致を求めず、encoding、改行、BOM、文字内容の4項目を記録します。変換先を原本と同じpathへredirectせず、同一filesystem上の一時fileへ出力してhashと代表行を承認後にrenameします。失敗時は一時fileだけを破棄し、保全した原本hashが変わっていないことを確認します。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次