2021年4月22日 星期四

PowerShell 如何把資料夾特定檔案 轉換至 UTF8 編碼

PowerShell 如何把資料夾特定檔案 轉換至 UTF8 編碼

tags: 部落格文章

會寫這篇是因為正在學得教程是中國來的 Eclipse 載入之後直接給我亂碼,要一個檔案慢慢添加個別轉換有夠煩的~

程序也搞了好久,先說 PowerShell5.1 不好用建議乖乖去載 PowerShell7.0來用。

順帶一提要解決 PowerShell5.1 用Out-File輸出帶BOM的問題,把編碼改成 ASCII 或是留空都不要打預設就好了。

本篇範例是用 PowerShell7.0 如果你的環境只能用5.1版,上面提到的在自己測試一下。

更新PS7

懶人包打指令,會自動跳出安裝檔一路下一步到底就好

iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI -Quiet"

或是下面官網手動下載,拖下去之後就有載點了
https://github.com/PowerShell/PowerShell

檔案轉換核心代碼

最關鍵的地方就是這裡啦,有點長我用個變數拆兩段,他是可以合體的。(合體之後記得前面整串$ct要括號起來)

    # 要被轉換的檔案位置與編碼
    $En1=GBK
    $F1='z:\file.txt'
    # 轉換後的檔案位置與編碼
    $En2=UTF8
    $F2='z:\file_UTF8.txt'

    $ct = Get-Content -Encoding $En1 $F1
    $ct | Out-File -Encoding $En2 $F2

這樣執行就可以轉換了,F2可以設置成跟F1 一樣就變成同一份檔案直接轉,但是非常不建議這樣做。不小心連續執行兩次檔案就毀了。

檔案編碼似乎是不能查的,我不知道為什麼用VScode這種近代的編輯器是怎麼偵測的,估計是演算法吧?因為也會有錯的時候所以肯定不是寫在檔案上。

寫成一行的範例

這邊還是要再提一次,當前版本的Windows只有內建的PS版本只到5還沒更新到PS7,PS7要自己手動下載,並且手動打開不會更新到系統上。

範例是把一個在Z:\的檔案 File.java,由 GBK 轉換到 UTF8

(Get-Content -Encoding GBK 'Z:\File.java') | Out-File 'Z:\File_UTF8.java'

要是跳出下面訊息
Get-Content : 無法繫結 ‘Encoding’ 參數。無法將 “GBK” 值轉換為 “Microsoft.PowerShell.Commands.FileSystemCmdletProv
單純只是舊版沒支援GBK而已,去升級吧XD。

批量轉換

這個大概是大家最關心的部分,整個把整資料夾裡面有 java 的全部都抓出來轉換到另一個目錄。

這次第一版半成品,那時候沒查到怎麼處理字串建資料夾的方式有點多此一舉。舊版本就不砍了,有需要功能完善的版本從底下連結自取。

## 初版
function  CovertFileEncoding_basic ($F1, $En1, $En2, $F2){
    $ct = (Get-Content -Encoding $En1 $F1)
    $ct | Out-File -Encoding $En2 -FilePath $F2
}
function  CovertFileEncoding ($F1, $En1, $En2, $F2, $tempPath){
    if (!(Test-Path -Path $tempPath)) {
        Write-Warning "暫存資料夾不存在"
    }
    $F2=$tempPath+$F2
    mkdir $F2 | Out-Null
    Remove-Item $F2
    CovertFileEncoding_basic $F1 $En1 $En2 $F2
}

# 轉換FilePath目錄下的所有java檔案,到tempPath目錄
function CovertDirEncoding($FilePath, $tempPath, $go=0) {
    $list = Get-ChildItem -Path $FilePath -Recurse -Filter *.java
    $listN = Get-ChildItem -Path $FilePath -Recurse -Filter *.java -Name
    for ($i = 0; $i -lt $list.Count; $i++) {
        $F1=$list[$i].FullName
        $F2=$listN[$i]
        if ($go -eq 0) {
            $F2
        } elseif ($go -eq 1){
            CovertFileEncoding $F1 "GBK" "UTF8" $F2 $tempPath
        }
    }
}

$FilePath = 'C:\Users\hunan\Desktop\JavaWeb\25\hotel2\src\'
$tempPath = 'Z:\temp\'
CovertDirEncoding $FilePath $tempPath

完整版

GitGub: https://github.com/hunandy14/DirCoverToUtf8

最底下的部分

# 路徑
$FilePath = "Z:\SourceCode\31"
$TempPath = $PSScriptRoot
cd $PSScriptRoot

預設只要更改 $FilePath 即可

變數 $TempPath 是複製的目的地,預設會自動建立在批次檔旁邊。
最後第三行單純只避免寫代碼的時候出事把目錄調到當前

詳細說明以後再寫,覺得八成還會再大動版本,還沒想到怎麼輸入排除檔案跟轉換檔案的方式。有寫應該會先更新在 github 上。

沒有留言:

張貼留言