如何让PowerShell处理文件名中的[或]? [英] How can I make PowerShell handle [ or ] in file name well?
问题描述
我从 PowerShell - 批量更改文件编码为 UTF-8 中修改了 PowerShell 脚本.
I modified PowerShell script from PowerShell - Batch change files encoding To 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:UsersAKULADesktopSRC" # source directory
$destination = "C:UsersAKULADesktopDST" # 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不能很好的处理[
or ]
.我制作了一些名称/内容多样化的测试文件.
But after using it, I've found that PS cannot handle [
or ]
well.
I made some test files that has diversity in name/content.
Get-Content : An object at the specified path C:UsersAKULADesktopSRCFILENAME[[[[[[]]]]]]]].txt does not exist, or
has been filtered by the -Include or -Exclude parameter.
At C:UsersAKULADesktopConvert_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://imgur.com/a/aN1RG2L
Since I cannot embed images in question, here is link of IMGUR album.
Full image list: https://imgur.com/a/aN1RG2L
这些是我测试过的:
- 测试文件有不同的名称.他们的名字包含空格,
'
,<代码>[]代码>.还组成了不同的语言(日语、韩语). - 这些文件具有相同的内容,使用 UCS-2 BE BOM(UTF-16 BE) 编码,因此我可以检查它是否已重新编码为 UTF-8.
- Test files have different names. Their name contains space,
'
,[]
. Also made up different language(Japanese, Korean). - These files have same content, encoded with UCS-2 BE BOM(UTF-16 BE) so that I can check if it has re-encoded to UTF-8.
如何让我的脚本很好地处理文件名中的[
或]
?
How can I make my script handle [
or ]
in file name well?
推荐答案
确实,使用 -LiteralPath
参数是最好的解决方案(在 PowerShell [Core] v6+ 中,可以缩短为 -lp
):
Indeed, use of the -LiteralPath
parameter is the best solution (in PowerShell [Core] v6+, you can shorten to -lp
):
$content = Get-Content -LiteralPath $i.Fullname
-LiteralPath
确保 $i.Fullname
被采用verbatim(字面意思);也就是说,路径中的 [
和 ]
被解释为它们本身而不是具有特殊含义(见下文).
-LiteralPath
ensures that $i.Fullname
is taken verbatim (literally); that is, [
and ]
in the path are interpreted as themselves rather than having special meaning (see below).
至于你尝试了什么:
$content = Get-Content $i.Fullname
实际上等同于:
$content = Get-Content -Path $i.Fullname
也就是说,传递给Get-Content
的(第一个)位置参数隐式绑定到-Path
参数.
That is, the (first) positional argument passed to Get-Content
is implicitly bound to the
-Path
parameter.
-Path
参数接受 通配符表达式允许通过模式匹配路径;除了支持 *
(任何字符运行)和 ?
(正好 1 个字符),[...]
里面通配符模式表示字符集 或范围(例如,[12]
或 [0-9]
).
The -Path
parameter accepts wildcard expressions to allow matching paths by patterns; in addition to support for *
(any run of characters) and ?
(exactly 1 character), [...]
inside a wildcard pattern denotes a character set or range (e.g., [12]
or [0-9]
).
因此,包含 [...]
的实际路径,例如 foo[10].txt
,不会被识别为这样,因为 [10]
被解释为与 单个 字符匹配的字符集,即 either 1
或 <代码>0代码>;即 foo[10].txt
将匹配 foo0.txt
和 foo1.txt
,但不是字面上名为 foo[10].txt
.
Therefore an actual path that contains [...]
, e.g., foo[10].txt
, is not recognized as such, because the [10]
is interpreted as a character set matching a single character that is either 1
or 0
; that is foo[10].txt
would match foo0.txt
and foo1.txt
, but not a file literally named foo[10].txt
.
当(隐式)使用 -Path
时,可以转义 [
和 ]
应该逐字解释的实例,即通过反引号 (`
),但请注意,当涉及引用和/或变量引用时,这可能会变得棘手.
When (implicitly) using -Path
, it is possible to escape [
and ]
instances that should be interpreted verbatim, namely via the backtick (`
), but note that this can get tricky to get right when quoting and/or variable references are involved.
如果你知道一个路径是文字路径,最好养成使用-LiteralPath
的习惯(在PowerShell Core 你可以缩短为 -lp
).
但是,如果您的路径包含 literal [
和 ]
并且您还需要通配符匹配,您必须使用 `
-escaping - 请参阅此答案.
However, if your path contains literal [
and ]
and you also need wildcard matching, you must use `
-escaping - see this answer.
这篇关于如何让PowerShell处理文件名中的[或]?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!