PowerShell - Пакетное изменение файлов в кодировке UTF-8
Я пытаюсь сделать чертовски простую вещь: изменить кодировку файлов с любого на UTF-8 без спецификации. Я нашел несколько скриптов, которые делают это, и единственный, который действительно работал для меня, это:https://superuser.com/questions/397890/convert-text-files-recursively-to-utf-8-in-powershell#answer-397915.
Это сработало, как и ожидалось, но мне нужны созданные файлы без спецификации. Поэтому я попытался немного изменить скрипт, добавив решение, приведенное к этому вопросу:Использование PowerShell для записи файла в UTF-8 без спецификации
Это мой последний сценарий:
foreach ($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$dest = $i.Fullname.Replace($PWD, "some_folder")
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
get-content $i | out-file -encoding $Utf8NoBomEncoding -filepath $dest
}
Проблема в том, что powershell возвращает мне ошибку, касающуюсяSystem.Text.UTF8Encoding($False)
строка с жалобой на неверный параметр:
Невозможно проверить аргумент в параметре «Кодировка». Аргумент «System.Text.UTF8Encoding» не принадлежит группе «Юникод, utf7, utf8, utf32, ascii», определенной атрибутом ValidateSet.
Интересно, я что-то упускаю, вроде версии powershell или чего-то в этом роде. Я никогда не кодировал скрипт Powershell раньше, поэтому я полностью потерян с этим. И мне нужно изменить кодировку этих файлов, их сотни, я бы не хотел делать это сам по себе.
На самом деле я использую версию 2.0, которая поставляется с Windows 7.
Заранее спасибо!
РЕДАКТИРОВАТЬ 1
Я попробовал следующий код, предложенный @LarsTruijens и другими сообщениями:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
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
}
$content = get-content $i
[System.IO.File]::WriteAllLines($dest, $content, $Utf8NoBomEncoding)
}
Это дает мне исключение, жалуясь на один из параметров для WriteAllLines:"Exception on calling 'WriteAllLines' with 3 arguments. The value can't be null". Parameter name: contents
, Однако скрипт создает все папки. Но они все пусты.
РЕДАКТИРОВАТЬ 2
Интересная вещь об этой ошибке - то, что параметр "содержимого" не нуль. Если я выведу значение переменной $ content (используя Write-host), строки будут там. Так почему же он становится нулевым, когда передается методу WriteAllLines?
РЕДАКТИРОВАТЬ 3
Я добавил проверку содержимого в переменную, поэтому скрипт теперь выглядит так:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
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
}
$content = get-content $i
if ( $content -ne $null ) {
[System.IO.File]::WriteAllLines($dest, $content, $Utf8NoBomEncoding)
}
else {
Write-Host "No content from: $i"
}
}
Теперь каждая итерация возвращает сообщение «Нет содержимого из: $ i», но файл не пустой. Есть еще одна ошибка:Get-content: can't find the path 'C:\root\FILENAME.php' because it doesn't exists.
Кажется, что он пытается найти файлы в корневом каталоге, а не в подпапках. Кажется, что он может получить имя файла из дочерних папок, но пытается прочитать его из корня.
РЕДАКТИРОВАТЬ 4 - Окончательная рабочая версия
После некоторой борьбы и следования советам, которые я получил здесь, особенно от @LarsTruijens и @AnsgarWiechers, я наконец сделал это. Мне пришлось изменить способ получения каталога из $ PWD и задать несколько фиксированных имен для папок. После этого все заработало отлично.
Вот оно, для тех, кто может быть заинтересован:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
$source = "path"
$destination = "some_folder"
foreach ($i in Get-ChildItem -Recurse -Force) {
if ($i.PSIsContainer) {
continue
}
$path = $i.DirectoryName -replace $source, $destination
$name = $i.Fullname -replace $source, $destination
if ( !(Test-Path $path) ) {
New-Item -Path $path -ItemType directory
}
$content = get-content $i.Fullname
if ( $content -ne $null ) {
[System.IO.File]::WriteAllLines($name, $content, $Utf8NoBomEncoding)
} else {
Write-Host "No content from: $i"
}
}