แปลงไฟล์ข้อความซ้ำเป็น UTF-8 ใน PowerShell


7

ฉันมีโฟลเดอร์ที่มีไฟล์ข้อความซึ่งมีโฟลเดอร์อื่นอยู่ด้วยและสิ่งเหล่านี้ก็มีไฟล์ข้อความบางไฟล์ ฉันต้องแปลงไฟล์เหล่านี้ซ้ำเป็นการเข้ารหัส UTF-8 ซ้ำใน PowerShell และเก็บรักษาโครงสร้างโฟลเดอร์ในระหว่างกระบวนการนี้ ฉันได้ลองสิ่งนี้แล้ว:

foreach( $i in get-childitem -recurse -name ) {
    get-content $i | out-file -encoding utf8 -filepath some_folder/$i
}

แต่มันไม่ทำงานมันไม่สามารถสร้างลำดับชั้นของโฟลเดอร์ ฉันจะรับมือกับปัญหานี้ได้อย่างไร


1
PowerShell รุ่นนี้เป็นรุ่นใด หนึ่งในที่มาพร้อมกับ (สำเนาของฉัน) Win7 (v2) ที่มีGet-ChildItemแต่ไม่Get-Children...
บ๊อบ

มันเป็นการสะกดที่ผิดฉันได้แก้ไขมันแล้ว
Roman

คำตอบ:


13

ลองอันนี้.

foreach($i in Get-ChildItem -Recurse) {
    if ($i.PSIsContainer) {
        continue
    }

    $dest = $i.Fullname.Replace($PWD, "some_folder")
    if (!(Test-Path $(Split-Path $dest -Parent))) {
        New-Item $(Split-Path $dest -Parent) -type Directory
    }

    get-content $i | out-file -encoding utf8 -filepath $dest
}

มันคว้าเส้นทางแบบเต็มของไฟล์และแทนที่ไดเรกทอรีปัจจุบันด้วยไดเรกทอรีที่คุณต้องการ ตัวอย่างเช่นคุณรันคำสั่งนี้ในไดเรกทอรีC:\1\( $PWD = C:\1\) หากพบไฟล์C:\1\2\file.txtก็จะให้การของ$destsome_folder\2\file.txt

สิ่งแรกถ้าบล็อกอยู่ที่นั่นคุณจึงไม่พยายามแปลงไดเรกทอรี

ไดเรกทอรีจะต้องมีการสร้างหากพวกเขายังไม่มีอยู่ - ฉันลืมไปแล้ว


หากคุณต้องการ UTF8 ที่ไม่มี BOM ให้แทนที่get-content $i | out-file -encoding utf8 -filepath $destบรรทัดดังต่อไปนี้ ( แหล่งที่มา ):

$filecontents = Get-Content $i
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
[System.IO.File]::WriteAllLines($i, $filecontents, $Utf8NoBomEncoding)

โปรดทราบว่าการดำเนินการนี้อาจไม่มีประสิทธิภาพสำหรับไฟล์ที่มีขนาดใหญ่กว่าเนื่องจากจะอ่านไฟล์ทั้งหมดลงในหน่วยความจำก่อนที่จะเขียนอีกครั้ง หากจำเป็นต้องใช้ประสิทธิภาพเป็นไปได้ที่จะอ่านทีละบรรทัดหรือแม้กระทั่งจำนวนไบต์ที่เฉพาะเจาะจงในแต่ละครั้ง อย่างไรก็ตามฉันควรเขียนโปรแกรมที่รวดเร็วใน C # ตามจุดนั้น (เนื่องจากคุณจะใช้. NET fuctions ใน PS ต่อไป)


มันไม่ทำงานสำหรับฉัน มันบอกว่ามีข้อผิดพลาดในบรรทัด 6 ($ dest ฯลฯ ... ) มันพยายามที่จะเรียกวิธีการที่มีอาร์กิวเมนต์เป็นโมฆะและมันผิด
Roman

ฉันไม่ได้ใช้ PowerShell มากพอดูเหมือนว่า .. ราคาไม่จำเป็น และไดเรกทอรีจะต้องสร้างขึ้นหากไม่มีอยู่ ฉันได้แก้ไขมันเพื่อแก้ไขปัญหานั้นและทดสอบในครั้งนี้จริง ๆ (มากกว่าแค่การสะท้อนเส้นทาง) ไม่แน่ใจว่าคุณได้รับข้อผิดพลาดนั้นอย่างไรคุณแทนที่some_folderด้วยอะไร
Bob

@ Roman คุณต้องกำหนด $ PWD มิฉะนั้น $ PWD จะเป็น NULL หากไฟล์ของคุณถูกเก็บไว้ใน "X: \ txt_Files" และคุณต้องการจัดเก็บไฟล์ที่แปลงแล้วใน "X: \ UTF_Files" ให้เพิ่ม: $ PWD = "X: \ txt_Files" และแทนที่ "some_folder" ด้วย "X: \ UTF_Files "
Martin

@Martin $PWDควรอ้างถึงไดเรกทอรีการทำงานปัจจุบันโดยอัตโนมัติ "some_folder"จะต้องถูกแทนที่ด้วยโฟลเดอร์ที่เหมาะสม
Bob

@Bob มันทำงานได้ตามที่คาดไว้ยกเว้นความจริงที่ว่ามันมีข้อผิดพลาดบางอย่างเกี่ยวกับไฟล์บางไฟล์ที่ไม่มีอยู่เพราะมันพยายามค้นหาไฟล์ในตำแหน่งที่ไม่ถูกต้อง จะเป็นอย่างไรถ้าฉันต้องการแปลงไฟล์เป็น UTF-8 ที่ไม่มี BOM ฉันต้องเพิ่มอะไรในสคริปต์นี้
darksoulsong

1
  • อนุญาตสำหรับไฟล์และโฟลเดอร์
  • ผู้ไม่เชื่อเรื่องนามสกุลไฟล์
  • เขียนทับไฟล์ต้นฉบับถ้าปลายทางเท่ากับพา ธ
  • การเข้ารหัสเป็นพารามิเตอร์

การใช้งาน: & "TextEncoding.ps1" -path "c: \ windows \ temps \ folder1" - การเข้ารหัส "UTF8"

นี่คือสคริปต์ที่ฉันสร้าง:

[CmdletBinding()]
param(  
    [Parameter(Mandatory=$true)]
    [string]$path,
    [Parameter(Mandatory=$false)]
    [string]$dest = $path,
    [Parameter(Mandatory=$true)]
    [string]$encoding
)

function Set-Encoding(){

    #ensure it is a valid path
    if(-not(Test-Path -Path $path)){

        throw "File or directory not found at {0}" -f $path
    }

    #if the path is a file, else a directory
    if(Test-Path $path -PathType Leaf){

        #if the provided path equals the destination
        if($path -eq $dest){

            #get file extension
            $ext = [System.IO.Path]::GetExtension($path)

            #create destination
            $dest = $path.Replace([System.IO.Path]::GetFileName($path), ("temp_encoded{0}" -f $ext))

            #output to file with encoding
            Get-Content $path | Out-File -FilePath $dest -Encoding $encoding -Force

            #copy item to original path to overwrite (note move-item loses encoding)
            Copy-Item -Path $dest -Destination $path -Force -PassThru | ForEach-Object { Write-Output -inputobject ("{0} encoded {1}" -f $encoding, $_) }

            #remove the extra file
            Remove-Item $dest   

        }else{

            #output to file with encoding
            Get-Content $path | Out-File -FilePath $dest -Encoding $encoding -Force     

        }

    }else{

        #get all the files recursively
        foreach($i in Get-ChildItem -Path $path -Recurse) {


            if ($i.PSIsContainer) {
                continue
            }

            #get file extension
            $ext = [System.IO.Path]::GetExtension($i)

            #create destination
            $dest = "$path\temp_encoded{0}" -f $ext

            #output to file with encoding
            Get-Content $i.FullName | Out-File -FilePath $dest -Encoding $encoding -Force

            #copy item to original path to overwrite (note move-item loses encoding)
            Copy-Item -Path $dest -Destination $i.FullName -Force -PassThru | ForEach-Object { Write-Output -inputobject ("{0} encoded {1}" -f $encoding, $_) }

            #remove the extra file
            Remove-Item $dest

        }

    }

}

Set-Encoding
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.