文字コードがShift-JISのファイル群をUTF-8(BOMなし)に一括置換するPowerShellスクリプト

大量のファイルの文字コードをShift-JISからUTF-8(BOMなし)に変換したいというケースを想定します。

ディレクトリ構造はネストあり、しかもhtmlやcssのファイルと画像などのファイル、テキストファイルとバイナリファイルがごちゃ混ぜにおいてあるカオスな状況です。

また、変換を実施する環境はWindows10上と仮定します。

そのため、PowerShellであれば環境に依存せずに済むだろう、ということで今回はPowerShellで挑戦しました。

param(
    [String]$in = ( Convert-Path . ) + "\src",
    [String]$out = ( Convert-Path . ) + "\dist",
    [String]$from = "Shift-JIS"
)

$enc_f = [Text.Encoding]::GetEncoding($from)
$enc_t = $( New-Object System.Text.UTF8Encoding($False))
Get-ChildItem $in -recurse |
ForEach-Object {
    if($_.GetType().Name -eq "FileInfo"){
        if($_.Extension.ToLower() -in @(".html",".htm",".js",".css",".pl",".cgi",".php",".twig")){
            $reader = New-Object IO.StreamReader($_.FullName, $enc_f)
            $o_path = $_.FullName.ToLower().Replace($in.ToLower(), $out)
            $o_folder = Split-Path $o_path -parent
            if(!(Test-Path $o_folder)){
                [Void][IO.Directory]::CreateDirectory($o_folder)
            }
            $writer = New-Object IO.StreamWriter($o_path, $false, $enc_t)
            while(!$reader.EndOfStream){$writer.WriteLine($reader.ReadLine())}
            $reader.Close()
            $writer.Close()
        }
    }
}

上の記事のスクリプトほぼそのままですが、2点ほど改修。

  • 単純に文字コードをUTF-8と文字列引数で指定するとBOMありに変換されてしまうので、UTF-8BOMなしに変換するように指定の部分を編集
  • バイナリファイルは無視するように、拡張子判定を追加して該当拡張子以外は変換を実施しないようにフィルタリング(拡張子はコード内の通りですが、今回は以下のものとしました)
    • .html
    • .htm
    • .js
    • .css
    • .pl
    • .cgi
    • .php
    • .twig

また、デフォルトの変換元ディレクトリと変換後ディレクトリを相対パスで指定しました。

> PowerShell .\encodeShifter.ps1

これでスクリプトを実行し、ひとまず課題をクリアしました。

ちなみにPowerShellの実行が制限されている環境では実行時にエラーで怒られることがあるとのことなので、その場合は

> PowerShell -ExecutionPolicy RemoteSigned  .\encodeShifter.ps1

というようにパラメータを付与してあげると良さそうです。

参考

大本のコード

文字列が配列の中の要素として含まれているか

拡張子

UTF-8 BOMなしを扱う

文字列結合

カレントディレクトリを取得

このシステムではスクリプトの実行が無効になっているため、ファイル……のエラー対処

この記事を書いた人

アバター

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。