文字コードをUTF-8に変換しまくるスクリプト

Eclipseで新規にプロジェクトを作るとWinやMacだと文字コードがデフォルトでShiftJISになっている。普通はプロジェクトのデフォルトエンコーディングUTF-8にソッコーで変更するが、たまに忘れてしまう。

見た目的には変わらないので何も気づかないままsvnとかgitで別のマシン(持ち歩き開発用にラップトップとかね)に共有する。そうすると元々のソースを作成したデスクトップがセットアップしたばかりのEclipseで、デフォルトエンコーディングShiftJISのままソースが格納されており、ラップトップ側のEclipseは設定を細かく変更してあり、プロジェクトのデフォルトエンコーディングUTF-8なので、プロジェクトの設定が「デフォルト」のままだとお互いの環境で「デフォルト」の定義が違うため片方の環境では常に文字化けしてしまう。(さらにこのままコーディングして保存>コミット>pushとかすると壊れた文字列がリポジトリに上がる)

ここで触れたケースではラップトップでプロジェクトのエンコーディングをShiftJISに明示的に指定すれば化けは治るが、今時ソースコードUTF-8で管理したいというのがナウい感覚だろう。そうすると、ソースファイルのエンコーディングを、(少なくともマルチバイト文字が含まれるファイルは)全てUTF-8に変換しなおさなければならないのだが、Eclipseにはそういう機能はいまのところないように見受けられる。

この問題はたまに起きてめんどくさいので、一括でディレクトリ以下を再起的にUTF-8に変換してくれるスクリプトを作った。Ruby1.9エンコーディングを含む文字列の扱いの習作にもなった。(つまりこのスクリプトruby1.9じゃないと動かないです)

#!/usr/bin/env ruby
# encoding: utf-8
require "kconv"

if ARGV.empty? then
  puts "give target directory"
  exit
end

target_dir = ARGV.first

def traverse(dir, &block)
  ignores = [".", "..", "bin", ".svn", ".git"] # 無視したいファイルやディレクトリがあったらここに書く
  Dir.foreach(dir) do |file|
    next if ignores.include?(file)
    file_abs_path = File.expand_path(file, dir)
    if FileTest.directory?(file_abs_path) then
      traverse file_abs_path, &block
    else
      block.call(file_abs_path)
    end
  end
end

def conv_utf8(file)
  puts "converting #{file}"
  File.open(file, "r+") do |fh|
    content = fh.read
    encoding = Kconv.guess(content)
    content.force_encoding(encoding)
    fh.truncate(0)
    fh.seek(0)
    fh.write(content.encode(Encoding::UTF_8))
  end
end

traverse(target_dir) do |f|
  conv_utf8(f)
end

使い方:

$ ruby convutf8.rb ./projectdir

などとして使うッス。