Chuyển đổi tệp văn bản đệ quy thành UTF-8 trong PowerShell


7

Tôi có một thư mục chứa các tệp văn bản bao gồm các thư mục khác trong đó và chúng cũng chứa một số tệp văn bản. Tôi cần chuyển đổi đệ quy tất cả các tệp này sang mã hóa UTF-8 trong PowerShell và bảo toàn cấu trúc thư mục trong quá trình này. Tôi đã thử điều này:

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

Nhưng nó không hoạt động, nó không thể tái tạo hệ thống phân cấp của các thư mục. Làm thế nào để tôi đối phó với vấn đề này?


1
Phiên bản nào của PowerShell là đây? Trong bản đi kèm (bản sao của tôi) Win7 (v2?), Có Get-ChildItemnhưng không Get-Children...
Bob

Đó là một lỗi chính tả, tôi đã sửa nó.
La Mã

Câu trả lời:


13

Hãy thử cái này

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
}

Nó lấy đường dẫn đầy đủ của tệp và thay thế thư mục hiện tại bằng thư mục bạn muốn. Ví dụ, bạn chạy lệnh này trong thư mục C:\1\( $PWD = C:\1\). Nếu nó tìm thấy các tập tin C:\1\2\file.txt, nó sẽ cung cấp cho bạn một $destsố some_folder\2\file.txt.

Khối đầu tiên nếu có, vì vậy bạn không thử chuyển đổi một thư mục.

Các thư mục phải được tạo nếu chúng chưa tồn tại - ban đầu tôi quên mất điều đó.


Nếu bạn muốn UTF8 không có BOM, hãy thay thế get-content $i | out-file -encoding utf8 -filepath $destdòng này bằng ( nguồn ) sau:

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

Lưu ý rằng điều này có thể không hiệu quả lắm đối với các tệp lớn hơn, vì nó đọc toàn bộ tệp vào bộ nhớ trước khi ghi lại chúng. Nếu cần hiệu quả, có thể đọc từng dòng hoặc thậm chí một số byte cụ thể tại một thời điểm. Tuy nhiên, tôi chỉ muốn viết một chương trình nhanh bằng C # vào thời điểm đó (vì dù sao bạn cũng đang sử dụng các phiên bản .NET trong PS).


Nó không làm việc cho tôi. Nó nói có lỗi trong dòng 6 ($ mệnh v.v ...). Nó cố gắng gọi một phương thức với đối số NULL và sai.
La Mã

Tôi đã không sử dụng PowerShell đủ, rõ ràng .. các trích dẫn là không cần thiết. Và các thư mục phải được tạo nếu chúng chưa tồn tại. Tôi đã chỉnh sửa nó để khắc phục điều đó và thực sự đã thử nghiệm lần này (không chỉ lặp lại các đường dẫn). Không chắc chắn làm thế nào bạn có lỗi đó, mặc dù, bạn đã thay thế some_folderbằng gì?
Bob

@Roman, Bạn cần xác định $ PWD, khác $ PWD là NULL. Nếu các tệp của bạn được lưu trữ trong "X: \ txt_Files" và bạn muốn lưu trữ các tệp đã chuyển đổi trong "X: \ UTF_Files", sau đó thêm: $ PWD = "X: \ txt_Files" và thay thế "some_folder" bằng "X: \ UTF_Files "
Martin

@Martin $PWDđược cho là tự động tham khảo thư mục làm việc hiện tại. "some_folder"không phải thay thế bằng thư mục thích hợp.
Bob

@Bob Nó hoạt động như mong đợi, ngoại trừ thực tế là nó đưa ra một số lỗi về một số tệp không tồn tại, vì nó cố gắng tìm tệp trên một vị trí không hợp lệ. Nếu tôi muốn chuyển đổi tập tin sang UTF-8 mà không có BOM thì sao? Tôi phải thêm gì vào kịch bản này?
darksoulsong

1
  • Cho phép tệp và thư mục
  • Mở rộng tập tin
  • Ghi đè tập tin gốc nếu đích bằng với đường dẫn
  • Mã hóa như một tham số

Cách sử dụng: & "TextEncoding.ps1" -path "c: \ windows \ temps \ folder1" -encoding "UTF8"

Đây là kịch bản tôi đã tạo:

[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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.