文字コードが分からないファイルを変換したい

iconv は変換元の文字コードを -f で指定する必要がある。手元のファイルがShift_JISとEUC-JPのどちらなのか分からない場合、まず判定してから変換しなければならない。

【iconv】ファイルの文字コードを変換する

nkf(Network Kanji Filter)は入力の文字コードを自動判定するため、変換先を指定するだけで変換できる。日本語の文字コードに特化しており、改行コードの変換や半角カナの扱いもまとめて処理する。

Debian系では apt install nkf、macOSでは brew install nkf でインストールする。

文字コードを判定する

--guess(短縮形は -g)でファイルの文字コードを判定する。改行コードも合わせて表示される。

$ nkf --guess utf8.txt
UTF-8 (LF)
$ nkf --guess sjis.txt
Shift_JIS (LF)
$ nkf --guess euc.txt
EUC-JP (LF)

複数のファイルを渡すとファイル名付きで出力する。

$ nkf --guess *.txt
euc.txt: EUC-JP (LF)
jis.txt: ISO-2022-JP (LF)
sjis.txt: Shift_JIS (LF)
utf8.txt: UTF-8 (LF)

BOM付きのUTF-8やWindowsの改行コードも区別する。

$ nkf --guess bom.txt
UTF-8 (BOM) (LF)
$ printf '日本語\r\n' | nkf --guess
UTF-8 (CRLF)

日本語を含まないファイルは ASCII、テキストでないファイルは BINARY と表示される。

$ printf 'hello\n' | nkf --guess
ASCII (LF)
$ head -c 200 /bin/ls | nkf --guess
BINARY

丸数字などの機種依存する文字を含むShift_JISは CP932 として判定する。

$ nkf --guess dep.txt
CP932 (LF)

文字コードを変換する

出力する文字コードをオプションで指定する。入力は自動判定されるため指定しなくてよい。

オプション出力する文字コード
-wUTF-8(BOMなし)
-w8UTF-8(BOM付き)
-sShift_JIS
-eEUC-JP
-jISO-2022-JP
-w16UTF-16(BOM付き、ビッグエンディアン)

Shift_JISのファイルをUTF-8に変換する例を示す。

$ nkf -w sjis.txt > utf8.txt

パイプの途中でも使える。

$ cat euc.txt | nkf -w
こんにちは、世界
日本語テキストのテスト

自動判定に頼らず入力の文字コードを明示する場合は --ic、出力を明示する場合は --oc を使う。

$ nkf --ic=CP932 --oc=UTF-8 sjis.txt > utf8.txt

ファイルを直接書き換える

--overwrite を付けると変換結果で元のファイルを置き換える。iconv では一時ファイルを経由する必要があった処理を1コマンドで実行できる。

$ nkf --guess data.csv
Shift_JIS (LF)
$ nkf -w --overwrite data.csv
$ nkf --guess data.csv
UTF-8 (LF)

複数のファイルをまとめて指定できるため、ディレクトリ内の一括変換も簡単である。

$ nkf -w --overwrite *.csv

--overwrite は元ファイルのタイムスタンプを保持する。更新時刻を変換した時刻にしたい場合は --in-place を使う。

$ stat -c '%n %y' a.txt b.txt
a.txt 2020-01-01 00:00:00.000000000 +0000
b.txt 2020-01-01 00:00:00.000000000 +0000
$ nkf -w --overwrite a.txt
$ nkf -w --in-place b.txt
$ stat -c '%n %y' a.txt b.txt
a.txt 2020-01-01 00:00:00.000000000 +0000
b.txt 2026-08-10 23:31:25.356845552 +0000

どちらもサフィックスを渡すと元のファイルをバックアップとして残す。

$ nkf -w --overwrite=.bak c.txt
$ nkf --guess c.txt c.txt.bak
c.txt: UTF-8 (LF)
c.txt.bak: Shift_JIS (LF)

改行コードを変換する

-L に続けて改行コードを指定する。文字コードの変換と同時に処理できる。

オプション改行コード
-LuLF(Unix)
-LwCRLF(Windows)
-LmCR(旧Mac)

Windowsの改行コードをUnixの改行コードに直しつつUTF-8へ変換する例を示す。

$ nkf -w -Lu --overwrite data.csv

-L を指定しなければ改行コードは変換されない。

$ printf 'a\r\nb\r\n' | nkf -Lu | od -An -c
   a  \n   b  \n

BOM を付ける・外す

iconv はUTF-8のBOMをU+FEFFとして素通しするため除去できないが、nkf は出力の指定でBOMを制御する。-w はBOMなし、-w8 はBOM付きで出力する。

$ od -An -tx1 bom.txt
 ef bb bf e3 81 82 41 0a
$ nkf -w bom.txt | od -An -tx1
 e3 81 82 41 0a
$ printf 'あA\n' | nkf -w8 | od -An -tx1
 ef bb bf e3 81 82 41 0a

Excelで開くCSVのようにBOMを求められる場面では -w8 を使う。

半角カナの扱いに注意する

nkf は初期状態で半角カナを全角カナに変換する。文字コードだけを変えたい場合は意図しない変換になるため注意する。

$ printf 'アイウ ハンカク\n' | nkf -w
アイウ ハンカク

半角カナをそのまま残すには -x を付ける。

$ printf 'アイウ ハンカク\n' | nkf -w -x
アイウ ハンカク

逆に全角カナを半角カナへ変換する場合は -Z4 を使う。

全角英数字を半角にする

-Z は全角の英数字と記号を半角に変換する。全角スペースを半角スペースにする場合は -Z1 を指定する。

$ printf 'ABC123 スペース\n' | nkf -w -Z
ABC123 スペース
$ printf 'ABC あ\n' | nkf -w -Z1 | od -c | head -1
0000000   A   B   C     343 201 202  \n

MIME ヘッダをデコードする

メールのSubjectなどでエンコードされた文字列は -m でデコードする。

$ printf 'Subject: =?ISO-2022-JP?B?GyRCRnxLXDhsGyhC?=\n' | nkf -w -m
Subject: 日本語

逆にMIMEエンコードする場合は -M を使う。-MB でbase64、-MQ でquoted-printableになる。

$ printf '日本語\n' | nkf -j -MB
GyRCRnxLXDhsGyhCCg==

iconv との使い分け

nkficonv
入力の文字コード自動判定-f で指定が必要
対応する文字コード日本語向けが中心1000種類以上
ファイルの直接書き換え--overwrite一時ファイルが必要
改行コードの変換-L で可能できない
UTF-8のBOM-w / -w8 で制御除去できない
インストール追加インストールが必要標準で利用可能

日本語のテキストを扱うなら nkf が扱いやすい。一方、日本語以外の文字コードを変換する場合や、追加インストールできない環境では iconv を使う。

【iconv】ファイルの文字コードを変換する

参考