如何使PowerShell能够很好地处理文件名中的[或]?

如何使PowerShell能够很好地处理文件名中的[或]?,powershell,path,glob,literals,Powershell,Path,Glob,Literals,我从中修改了PowerShell脚本 #的修改版本https://stackoverflow.com/q/18684793 [Threading.Thread]::CurrentThread.CurrentUICulture='en US' $Encoding=New Object System.Text.UTF8Encoding($True)#如果UTF8Encoding($False),它将是不带BOM的UTF-8 $source=“C:\Users\AKULA\Desktop\SRC”#源

我从中修改了PowerShell脚本

#的修改版本https://stackoverflow.com/q/18684793
[Threading.Thread]::CurrentThread.CurrentUICulture='en US'
$Encoding=New Object System.Text.UTF8Encoding($True)#如果UTF8Encoding($False),它将是不带BOM的UTF-8
$source=“C:\Users\AKULA\Desktop\SRC”#源目录
$destination=“C:\Users\AKULA\Desktop\DST”#目标目录
如果(!(测试路径$destination)){
新项目-路径$destination-项目类型目录| Out Null
}
#删除以前生成的所有文件
Get-ChildItem-Path$destination-Include*-File-Recurse | ForEach对象{$\.Delete()}
#递归地将所有文件转换为UTF-8
foreach($i in Get ChildItem$source-Force-Recurse-Exclude“desktop.ini”){
如果($i.PSIsContainer){
持续
}
$name=$i.Fullname.Replace($source,$destination)
$content=获取内容$i.Fullname
如果($null-ne$content){
[System.IO.File]::writeAllines($name、$content、$Encoding)
}否则{
编写主机“没有来自:$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相册的链接。
完整图像列表:

这些是我测试过的:

  • 测试文件有不同的名称。它们的名称包含空格,
    []
    。也组成了不同的语言(日语、韩语)
  • 这些文件具有相同的内容,使用UCS-2 BE BOM(UTF-16 BE)编码,因此 我可以检查它是否重新编码为UTF-8

如何使脚本能够很好地处理文件名中的
[
]

事实上,使用
-LiteralPath
参数是最好的解决方案(在PowerShell[Core]v6+中,可以缩短为
-lp
):


-LiteralPath
确保
$i.Fullname
是逐字(字面)获取的;也就是说,路径中的
[
]
被解释为它们自己,而不是具有特殊意义(见下文)


至于你所尝试的:

$content = Get-Content $i.Fullname
实际上与以下内容相同:

$content = Get-Content -Path $i.Fullname
也就是说,传递给
Get Content
的(第一个)位置参数隐式绑定到
-路径
参数

-Path
参数接受
以允许按模式匹配路径;除了支持
*
(任何字符运行)和
(正好1个字符),
[…]
内的通配符模式表示字符集或范围(例如,
[12]
[0-9]

因此,包含
[…]
的实际路径(例如
foo[10].txt
)无法识别为该路径,因为
[10]
被解释为与单个字符匹配的字符集,该字符集是
1
0
;这就是
foo[10].txt
将匹配
foo0.txt
foo1.txt
,但不是字面上命名为
foo[10].txt的文件

当(隐式地)使用
-Path
时,可以转义应该逐字解释的
[
]
实例,即通过反勾(
`
),但请注意,当涉及引用和/或变量引用时,这可能会变得很难正确


如果您知道路径是文本路径,最好养成使用
-LiteralPath
的习惯(在PowerShell Core中,您可以将其缩短为
-lp


但是,如果路径包含literal
[
]
并且还需要通配符匹配,则必须使用
`
-escaping
-请参见。

-LiteralPath
-path
PowerShell处理方括号
[]
类似于正则表达式中的字符类。@PetSerAl您的意思是
$content=Get content-LiteralPath$i.Fullname
$content = Get-Content -Path $i.Fullname