Перетворення текстових файлів рекурсивно в 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...
Bob

Це була помилка, я її виправив.
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, це дасть вам $dest з some_folder\2\file.txt.

Перший блок, якщо є, тому ви не намагаєтеся конвертувати каталог.

Каталоги повинні бути створені, якщо вони ще не існують - я спочатку це забув.


Якщо ви бажаєте використовувати UTF8 без специфікації, замініть 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 і т.д. ...). Він намагається викликати метод з аргументом NULL і його помилковим.
Roman

Я не використав PowerShell достатньо, мабуть .. котирування не потрібні. І каталоги повинні бути створені, якщо вони ще не існують. Я відредагував його, щоб виправити це, і насправді перевірив його цього разу (більше, ніж просто повторюючи шляхи). Не знаю, як ви отримали цю помилку, але що ви замінили some_folder з?
Bob

@Roman, Ви повинні визначити $ PWD, інакше $ PWD є NULL. Якщо ваші файли зберігаються у файлі "X: x_xtiles" і ви хочете зберегти перетворені файли в "X: UTF_Files", то додайте: $ PWD = "X: x_xtiles" і замінити "some_folder" на "X: UTF_Files "
Martin

@Martin $PWD передбачається автоматично посилатися на поточний робочий каталог. "some_folder" має бути замінено на відповідну папку.
Bob

@Bob Працював так, як очікувалося, за винятком того, що він викидає деякі помилки про деякі файли, які не існують, тому що він намагається знайти файл на недійсному місці. Що робити, якщо я хочу конвертувати файли в UTF-8 без специфікації? Що мені потрібно додати до цього сценарію?
darksoulsong

1
  • Дозволяє файли і папки
  • Розширення файлу агностик
  • Перезаписує вихідний файл, якщо адресат дорівнює шляху
  • Кодування як параметр

Використання: & amp; "TextEncoding.ps1" - шлях "c: вікна оновлення папки1" -кодування "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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.