Windowsで作成された Shift_JIS のファイルを受け取って、Unix/UTF-8 に変換し諸々処理を施したあと、結果ファイルをWindows形式のファイルに変換して返す…という作業を仕事でよくやります。
この変換をパパっとこなすために、作業をシェルスクリプトにまとめてコマンド化しています。
ちなみに、Unix環境(実際は Mac OS X ですが)で EUC-JP ではなく UTF-8 を使用しているのはなぜかというと、僕の仕事環境ではデータベースに SQLite を使用しているためです(※ SQLite には、格納できる文字コードが Unicode のみという縛りがあります)。
nkfコマンドのインストール
エンコードの変換といえば iconvコマンドが一般的ですが、漢字を含む日本語ファイルのエンコードを変換するのに、nkf という優れたコマンドが配布されてます。
一部の Linuxディストリビューションでは標準で nkf がインストールされているようですが、Mac OS X Mountain Lion 以下では今のところ自分で入れなくてはいけません($ which nkf と探しても「おりません」と言われると思います)。
(※ ちなみに Ubuntu desktop 12.10 でも確認してみましたが、nkf は追加でインストールする必要があるようです。)
Mac への nkf のインストールは至って簡単です。
下記のように MacPorts からインストールできます。
まず、nkf の所在を確認します。
$ port search nkf nkf @2.1.3 (textproc, japanese) Network Kanji code conversion Filter
「portなんてコマンド知らんよ」と怒られてしまった方は、MacPorts のインストールから先に行なってください。
nkf の所在が確認できたら下記の要領でインストールします。
sudo で実行しますのでパスワードの入力を求められます。
$ sudo port install nkf
これで nkf のインストールは完了です。
一応確かめましょう。
$ which nkf /opt/local/bin/nkf
上記のように nkf のインストールされた場所が表示されればOKです。
試しに適当なテキストファイルの現在のエンコードを確認してみましょう。
エンコードの確認には -gスイッチを付けます。
$ nkf -g file_name UTF-8
シェルスクリプトの作成
作成するシェルスクリプトの要件は次の通りです。
- 指定したファイルのエンコードを確認して…
- UTF-8 だったら Windows 向けの Shift_JIS(改行は CrLf)のファイルを作成、
- UTF-8 以外だったら Mac で作業が行えるように UTF-8(改行はLf)のファイルを作成
- 「encf」(名前はお好きに)というコマンド名でどこからでも実行できるように
出来上がったシェルスクリプトを /usr/local/bin に格納
まず、シェルスクリプトの中身は次のようなものを作成しました。
#!/bin/sh # # $ encf file... # From Unix/UTF-8 To Windows/Shift_JIS # or # From Windows/Shift_JIS To Unix/UTF-8 echo '------------------------' for fFile in "$@" do echo "fromFile: ${fFile}" # Check encode (fromFile) current_enc=`nkf -g "$fFile"` str="Encode From ${current_enc}" # toFile toFile= if [ $current_enc = "UTF-8" ] then # Conv Windows Shift_JIS \r\n toFile="Shift_JIS_"$fFile nkf --windows "$fFile" > "$toFile" else toFile="UTF-8_"$fFile # Conv Unix EUC-JP \n nkf --unix "$fFile" > "$toFile" # From EUC-JP To UTF-8 nkf -w --overwrite "$toFile" fi # Check encorde (toFile) to_enc=`nkf -g "$toFile"` str="${str} To ${to_enc}" echo $str echo "toFile: ${toFile}" echo '------------------------' done
ざっくりと要点だけ解説すると…
for fFile in "$@"
で、コマンド引数に指定したファイルを順番に変数 fFile (fromFile) に読み込んでいます。
current_enc=`nkf -g "$fFile"`
変数 current_enc (Currnt Encode) に nkf でチェックしたエンコードの種類を格納しています。
if [ $current_enc = "UTF-8" ]
個人的な作業に最適化して、エンコードが UTF-8 かそれ以外かで条件分岐させています。
nkf --windows "$fFile" > "$toFile"
nkf は –windowsスイッチを付けるだけで、エンコードが Shift_JIS、改行コードが CrLf のファイルを生成してくれます。
nkf --unix "$fFile" > "$toFile" nkf -w --overwrite "$toFile"
同様に –unixスイッチでUnix用のファイルを生成してくれますが、エンコードが EUC-JP、改行コードが Lf になります。
改行コードはこれで良いのですが、エンコードは UTF-8 にしたいので、-wスイッチを置くことによって UTF-8 に変換し、–overwriteスイッチでファイルを上書きしています。
str="${str} To ${to_enc}"
表示するメッセージを文字列結合して変数に代入している箇所の補足です。
Perl なんかだと $str = $str . ” To ” . $to_enc; と書けそうなところですが、シェルスクリプトだと上記のような書き方になります。
文字列全体を ” で囲っているのは、中に含まれる変数を展開するためです。
また、変数自体を ${} で囲っているのは、文字列内で「ここは変数の値が展開されるよ」と明示的に書くことによって、曖昧さを回避しています。
ついでに言うと、シェルスクリプト内のコマンド引数に変数を指定するとき “$fFile” のように ” で変数を囲っているのは、変数が展開された時、文字列(ファイル名など)にスペースが含まれていても、それは一つながりの文字列だよとコマンドに教えてあげるためのクォーティングとなります。
(※ コマンドラインでは、それぞれの変数がクォーティングされていないとき、スペースが引数の切れ目と解釈されてしまいます。)
作成したファイルを encf という名前で保存し、次のコマンドでパーミッションを変更します。
chmod a+x encf
カレントディレクトリでテストしてみましょう。
$ ./encf file_name ------------------------ fromFile: file_name Encode From Shift_JIS To UTF-8 toFile: UTF-8_file_name ------------------------
上記のようにうまく動作することが確認できたら、いつでも使えるように /usr/local/bin に移動します。
$ sudo cp encf /usr/local/bin/encf
これで自作した encfシェルスクリプトが、どこからでも encfコマンドとして利用できるようになります。
$ encf file_name