過去にWindowsで書いたテキストファイルは、文字エンコードが原因でLinuxではそのままでは読めません。エディタで文字エンコードを手動で変えるか自動検知するかすればよいのですが、ファイルの整理をしていることもあって文字エンコードをUTF-8に一括変換しました。
# !/bin/sh
find . -type f -exec grep . -Iq {} \; -exec nkf -w -Lu --overwrite {} \; -and -print
# The function of this script is to convert the character encoding
# of all japanese text files under current direcotory to UTF-8
# (-w option in nkf).
# When you want to unify a different character encoding,
# change the option -w in nkf as
# -j ISO-2022-JP,
# -s Shift-JIS,
# -e EUC-JP,
# -w UTF-8.
# When you want other newline character, change the option -Lu in nkf as
# -Lw CRLF(for Windows),
# -Lm CR,
# -Lu LF.
# If your os don't have nkf, you need to install nkf.
# (i.e. $ sudo apt-get install nkf)
# The parts of the script is quoted by
# http://stackoverflow.com/questions/4767396/linux-command-how-to-find-only-text-files
# for extract all text files under current directory:
# $ find . -type f -exec grep . -Iq {} \; -and -print
このスクリプトはカレントディレクトリ下にあるすべてのテキストファイルの文字エンコードをUTF-8に、改行コードをLFに変換して統一します。カレントディレクトリ以下の階層にディレクトリがあっても機能します。nkf(Network Kanji Filter)を使うので、使用環境にインストールされていない場合は$ sudo apt-get install nkf
などでインストールする必要があります。nkfがサポートしている文字エンコードのShift-JISやEUC-JPなどのすべてのテキストファイルをUTF-8に変換して上書き保存します。文字エンコードを変換・上書き保存したテキストファイルのパスを標準出力して終了します。
findとgrepでカレントディレクトリ以下のすべてのテキストファイルを得る方法は、Linux command: How to 'find' only text files? - Stack Overflow に習いました。grep -I
オプションはバイナリファイルを無視する役割です。他にも役に立つ説明が書いてあります。
nkfの使い方についてnkfコマンド - hydroculのメモを読みました。nkf -w -Lu
オプションを変えることで他の文字エンコードに変換することもできます。上記スクリプトのコメントにオプションを簡単にまとめています。
他の方法で、例えば$ iconv -f Shift-JIS -t UTF-8 filename
でも文字エンコードの変換はできますが、iconvでは、変換前の文字エンコードを指定する必要があります。
はじめはfileコマンドでファイル毎に文字エンコードを判別して、iconvで文字エンコード変換しようと思いました。
しかし、試しにEUC-JP、Shift-JIS、UTF-16、UTF-8の4種類のテキストファイルを用意して、fileで文字エンコードを判別しようとすると
# 文字エンコードが異なる4つのテキストファイルを用意する
$ iconv -f UTF-8 -t EUC-JP testfile_utf8 > testfile_eucjp
$ iconv -f UTF-8 -t Sihft-JIS testfile_utf8 > testfile_sjis
$ iconv -f UTF-8 -t UTF-16 testfile_utf8 > testfile_utf16
# 4つのテキストファイルそれぞれの文字エンコード方式を得る
$ for f (*) {file --mime-encoding $f}
testfile_eucjp: unknown-8bit
testfile_sjis: unknown-8bit
testfile_utf16: utf-16le
testfile_utf8: utf-8
となり、EUC-JPとShift-JISがどちらもunknown-8bitとなり区別できません。
この点nkfはよくできていて、nkfが対象のテキストファイルの文字エンコードを判別するので、ユーザーは変換前の文字エンコードを指定しなくてよいです。
以上、文字エンコード方式が異なる複数テキストファイルを一括変換して文字エンコードを統一するTipsでした。