我正在尝试做一件非常简单的事情:将文件编码从任何东西更改为没有 BOM 的 UTF-8。我发现了几个执行此操作的脚本,唯一对我有用的是这个:https ://superuser.com/questions/397890/convert-text-files-recursively-to-utf-8-in-powershell#回答 397915。
它按预期工作,但我需要没有 BOM 的生成文件。所以我试着稍微修改一下脚本,添加给这个问题的解决方案:Using PowerShell to write a file in UTF-8 without the BOM
这是我的最终脚本:
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”不属于 ValidateSet 属性指定的组“unicode, utf7, utf8, utf32, ascii”。
我想知道我是否缺少某些东西,例如 powershell 版本或类似的东西。我以前从未编写过 Powershell 脚本,所以我完全迷失了。而且我需要更改这些文件编码,它们有数百个,我不想自己一个一个做。
其实我用的是Windows 7自带的2.0版本。
提前致谢!
编辑 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 方法时变为 null 呢?
编辑 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"
}
}
现在每次迭代都会返回“No content from: $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"
}
}