我将 PowerShell 脚本从 PowerShell - 批量更改文件编码更改为 UTF-8。
# Modified version of https://stackoverflow.com/q/18684793
[Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US'
$Encoding = New-Object System.Text.UTF8Encoding($True) # If UTF8Encoding($False), It will be UTF-8 without BOM
$source = "C:\Users\AKULA\Desktop\SRC" # source directory
$destination = "C:\Users\AKULA\Desktop\DST" # destination directory
if (!(Test-Path $destination)) {
New-Item -Path $destination -ItemType Directory | Out-Null
}
# Delete all previously generated file
Get-ChildItem -Path $destination -Include * -File -Recurse | ForEach-Object {$_.Delete()}
# Recursively convert all files into UTF-8
foreach ($i in Get-ChildItem $source -Force -Recurse -Exclude "desktop.ini") {
if ($i.PSIsContainer) {
continue
}
$name = $i.Fullname.Replace($source, $destination)
$content = Get-Content $i.Fullname
if ($null -ne $content) {
[System.IO.File]::WriteAllLines($name, $content, $Encoding)
} else {
Write-Host "No content from: $i"
}
}
但是使用后发现PS不能很好地处理
[
或]
。
我制作了一些名称/内容具有多样性的测试文件。
Get-Content : An object at the specified path C:\Users\AKULA\Desktop\SRC\FILENAME[[[[[[]]]]]]]].txt does not exist, or
has been filtered by the -Include or -Exclude parameter.
At C:\Users\AKULA\Desktop\Convert_to_UTF-8.ps1:24 char:16
+ $content = Get-Content $i.Fullname
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (System.String[]:String[]) [Get-Content], Exception
+ FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetContentCommand
由于我无法嵌入有问题的图像,这里是 IMGUR 专辑的链接。
完整图片列表:https://i.sstatic.net/LtSBS.jpg
这些是我测试过的:
'
,
[]
。还制作了不同的语言(日语,韩语)。如何让我的脚本很好地处理文件名中的
[
或 ]
?
tl;博士
确实,使用
-LiteralPath
参数是最好的解决方案(在 PowerShell (Core) v6+ 中,您可以缩短为 -lp
):
$content = Get-Content -LiteralPath $i.Fullname
-LiteralPath
确保$i.Fullname
被逐字记录(字面意思);也就是说,路径中的 [
和
]
被解释为本身 而不是具有 特殊含义 ,因为它们被解释为 通配符表达式,因此它们将作为
-Path
参数 - 请注意,如果您只传递 值(字符串)作为第一个参数,则 -Path
是 位置隐含的,就像您所做的那样 (Get-Content $i.FullName
)注意:此答案类似地
适用于同时具有 -Path
和
-LiteralPath
参数allcmdlet,例如
Set-Content
、Out-File
和 Set-Location
。
你尝试过的:
$content = Get-Content $i.Fullname
实际上等同于:
$content = Get-Content -Path $i.Fullname
也就是说,传递给 Get-Content
的(第一个)positional 参数隐式绑定到
-Path
.
-Path
参数接受
通配符表达式以允许通过模式匹配路径;除了支持
*
(任何字符串)和 ?
(恰好 1 个字符)之外,通配符模式内的 [...]
表示字符集或范围(例如,
[12]
或[0-9]
)。
因此,包含
[...]
(例如 foo[10].txt
)的实际路径不会
被识别为这样,因为
[10]
被解释为与 单个字符匹配的字符集,即either
1
或 0
;也就是说
foo[10].txt
将匹配
foo0.txt
和
foo1.txt
,但不是字面名为
foo[10].txt
的文件。
当(隐式)使用
-Path
时,可以
转义
[
和]
实例,这些实例应该逐字解释,即通过反引号(
`
),但请注意当涉及引用和/或变量引用时,这可能会变得很棘手。如果您知道路径是文字路径,最好养成使用
-LiteralPath
的习惯(在 PowerShell Core
中您可以缩写为
-lp
)。
但是,如果您的路径包含literal
[
和 ]
并且您
also需要通配符匹配,则必须使用
`
-escaping - 请参阅此答案。不幸的是,至少在两种情况下,该解决方案的好建议并不成立。
Get-Content -LiteralPath "nobox[]"
Get-Content : An object at the specified path box[] does not exist, or has been filtered by the -Include or -Exclude parameter.
At line:1 char:1
+ Get-Content -Path "nobox[]"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (System.String[]:String[]) [Get-Content], Exception
+ FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : Cannot find path 'nobox' because it does not exist.
At line:1 char:1
+ Get-Content -LiteralPath "nobox"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nobox:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
因此,要默默地处理可选文件,但不要直截了当地抑制每个异常,例如:
try {
$lines = Get-Content -LiteralPath $path -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
$lines = @()
}
用括号阻塞路径。
创建硬链接或符号链接
次要和主要警告:
Path
-LiteralPath
来澄清这一点。链接的目标
Value
参数(在v5中秘密地称为
Target
New-Item -ItemType "HardLink" -Path "whatever" -Target "*"
使 Powershell 尖叫“无法设置位置,因为路径 '*' 解析为多个容器。”。New-Item -ItemType "HardLink" -Path "whatever" -Target "f[]"
这将创建一个链接:
New-Item -ItemType "HardLink" -Path "f[2]" -Target ([WildcardPattern]::Escape("f[]"))
与 ItemType“SymbolicLink”相同。