2019年2月23日土曜日

PowerShellでファイルの一覧を、BOMなしのUTF-8ファイルに出力する方法

前回の記事で、ファイルの一覧をEXPORT-CSVを使ってファイル出力したのですが、これには大きな制約がありました。

EXPORT-CSVでCSVファイルを簡単に作れるのは素晴らしい事なのですが、いかんせん文字コード「UTF-8」は、必ずバイトオーダーマーク「BOM」が付く形式になってしまうのでした。

そこで、今回は、便利なEXPORT-CSVではなく、自力で「文字コード」をBOMなしUTF-8に指定し、ファイルをテキストファイルに書き込もうという方針です。



$F = (GET-CHILDITEM "C:\Windows\SysWow64" | ?{$_.EXTENSION -match ".EXE" -and !($_.PSIsContainer)}) 
$F2= ($F | SORT @{Expression="LastWriteTime";Descending=$true},Name)
$F3="";$F2 | %{ $F3+=($_.Directory.ToString()+","+$_.Name+","+$_.LastWriteTime.ToString("yyyyMMdd,HHmmss")+","+$_.Length.ToString()+"`r`n")} 
$ENC=NEW-OBJECT System.Text.UTF8Encoding -ArgumentList @($false)
[System.IO.File]::WriteAllLines("C:\Temp\FILELIST2.CSV",$F3,$ENC)

↑コマンドの流れは以下のようになります。

  • (1)ファイルの一覧を取得するところまでは前回と同じく、2段階に分けてみました
  • (2)違いは3行目からです
  • (3)配列$F3に、ファイル情報を元にして、自力でカンマ区切り形式文字列を作り出して格納
  • (4)配列を文字コードBOMなしUTF-8でファイルに書き込み
↑実行すると、ちゃんとBOMなしのUTF-8となります。

昔のテキストエディタだと、BOMのありなしはよく分からない事がありましたが、 ちなみに文字コードですが、以下のようにします。

$ENC=NEW-OBJECT System.Text.UTF8Encoding -ArgumentList @($false)

-ArgumentListでパラメータの配列を投げ込むのですが、ここでBOMなしになります。

他の書き方としては、

ENC=[System.Text.Encoding]::GetEncoding("UTF-8")

と書けば短くて良いのでは??と思われるでしょうが、これだとBOMが付いてしまうのです。

ちなみに、トラブルの元として名高いWindowsのメモ帳ですが、有無も言わせずにBOM付きUTF-8で保存する上に、文字コードの表示もしない仕様なので、他の文字コード前提のアプリケーションの挙動を無意識に壊してしまう・・・という所に原因がありそうです。

ただ、PowerShellは、バージョンによって挙動が変化したりするかも知れないので、バージョンによって確認が必要かも知れないですね。

今日現在のWindows 10に実装されているPowerShellバージョンは、コマンド「$PSVERSIONTABLE」で確認できるのですが、 5.1.17763.316(長い)です。