之前研究 PowerShell 中文編碼問題有個結論 - Windows 10 內建 PowerShell 5.1,在中文版 Windows 預設用 BIG5 編碼,PowerShell 6.0 之後會預設改用 UTF8。因此我一直以為 .\Do-Something.ps1 > output.txt 存檔是用 ANSI/BIG5 編碼,但事實不然。

前天介紹的 Windows 資料夾權限清單產生小工具有個用法是修改權限前先 .\List-Acl.ps1 C:\WWW | ConvertTo-Json > before.json做一次快照,修改後再做一次 .\List-Acl.ps1 C:\WWW | ConvertTo-Json > after.json,之後可用 git diff before.json after.json產生差異對照表,但實測時卻踩到雷:

git diff 判定我的 json 檔是二進位資料無法比對,但 type after.json 看是純文字無誤。

用 NotePad++ 開啟 after.json,謎底揭曉 - 用 > file.txt 儲存成的文字檔,編碼並非我預期的 ANSI/BIG5,而是 Unicode (UCS-2 LE BOM/UTF-16 LE):

MS Docs 有篇關於 PowerShell 編碼原則的完整說明 - about_Character_Encoding - PowerShell

整理重點如下:

  • PowerShell 5.1 支援以下編碼:Ascii、BigEndianUnicode、BigEndianUTF32、Byte、Default、Oem、Unicode/String/Unknown(即 UTF-16 LE)、UTF32、UTF7、UTF8(含 BOM)
  • PS 5.1 預設使用 Unicode (UTF16-LE),但有些 Cmdlet 有自己的編碼偏好:

    Out-File、>、>> 用 UTF-16LE Add-Content、Set-Content、Send-MailMessage 用 Default Export-Csv 建立用 ASCII,附加現成檔案時則沿用其編碼 Export-PSSession 用 UTF8(含 BOM) New-Item -Type File -Value 會建立 UTF8 (不含BOM) Start-Transcript 建立用 UTF8(含 BOM),附加現成檔案時則沿用其編碼

  • PowerShell Core (V6+) 支援的編碼:ascii、bigendianunicode、oem、unicode、utf7、utf8、utf8BOM、utf8NoBOM、utf32,所有輸出預設都是用 utf8NoBOM
  • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' 可修改特定 Cmdlet 的編碼、$PSDefaultParameterValues['*:Encoding'] = 'utf8' 則可修改全部 Cmdlet 的編碼
  • $OutputEncoding 修改對外部程式使用的編碼,但「不包含 > 輸出導向」

實測,設定 $PSDefaultParameterValues['*:Encoding'] = 'utf8' 後,.\List-Acl.ps1 C:\WWW | ConvertTo-Json > after-utf8.json 即會改用 UTF-8 BOM 編碼,而我也如願用 git diff 取得修改對後對照:

Notes about how PorwerShell decide output encoding.


Comments

Be the first to post a comment

Post a comment