powershell - 如何让 PowerShell 很好地处理文件名中的 [ 或 ] ?

标签 powershell path glob literals

我修改了 PowerShell - Batch change files encoding To UTF-8 中的 PowerShell 脚本.

# 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 专辑的链接。
完整图片列表:/image/LtSBS.jpg

这些是我测试过的:

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

如何让我的脚本很好地处理文件名中的 []

最佳答案

tl;博士

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

$content = Get-Content -LiteralPath $i.Fullname

-LiteralPath 确保 $i.Fullname 被逐字记录(字面意思);也就是说,路径中的 [] 被解释为它们本身,而不是像它们那样具有特殊含义由于被解释为 wildcard expression 作为 -Path 参数 - 请注意,如果您仅传递(字符串),则 -Path位置隐含的作为第一个参数,就像您所做的那样 (Get-Content $i.FullName)

注意:此答案类似地适用于同时具有 -Path
-LiteralPath 参数的所有 cmdlet
,例如Set-Content , Out-File ,和Set-Location .


至于你尝试过的:

$content = Get-Content $i.Fullname

实际上等同于:

$content = Get-Content -Path $i.Fullname

也就是说,传递给 Get-Content 的(第一个)位置参数隐式绑定(bind)到
-Path 参数

-Path 参数接受 wildcard expressions 允许通过模式匹配路径;除了支持 *(任何字符运行)和 ?(正好 1 个字符)之外,还支持 [...]通配符模式表示字符集或范围(例如[12][0-9])。

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

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

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

但是,如果您的路径包含文字 [] 并且您需要通配符匹配,您必须使用 `-escaping - 请参阅 this answer .

关于powershell - 如何让 PowerShell 很好地处理文件名中的 [ 或 ] ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57755417/

相关文章:

python - 如何使用 glob() 递归查找文件?

ruby - 寻找 。 - 在 ruby​​ 中输入 f

powershell - 如何忽略字母/单词?

forms - "Are you sure?"通过 powershell 中的消息框

powershell - VS Code 总是提示 : "older version of PackageManagement known to cause issues"

powershell - 如何在foreach对象循环中找到当前对象的路径

algorithm - 优化/简化路径

java - Files.walk 似乎没有进入子文件夹 Java

python - 如何在 anaconda 提示符下运行 powershell 脚本?

c++ - 有没有办法仅对斜杠的第一个实例应用 fnmatch 的 FNM_PATHNAME 标志?