如何使用 Invoke-WebRequest 的 -OutFile 参数转义文件路径中的方括号

Chr*_*son 4 powershell glob escaping

当您[1]在文件名中包含类似File[1].txtInvoke-WebRequest-OutFile参数一起使用的内容时,您会收到错误消息Cannot perform operation because the wildcard path File[1].txt did not resolve to a file.

这是由此处记录的行为引起的。

对于其他 cmdlet,您可以-LiteralPath用来强制按字面意思采用路径,但在这种情况下,这不是一个选项。

我试过用 ` or转义[]字符,\但它仍然给出同样的错误。

为了简化测试时,可以重现相同的问题有Out-FileTest-Path等等。

#Fails
Out-File -FilePath "file[1].txt"
Out-File -FilePath "file`[1`].txt"
Out-File -FilePath "file\[1\].txt"

#Succeeds
Out-File -LiteralPath "file[1].txt"

#Fails
Test-Path -Path "file[1].txt"

#Succeeds
Test-Path -LiteralPath "file[1].txt"
Run Code Online (Sandbox Code Playgroud)

我怎样才能逃避将被用来表示在通配符的字符-Path-FilePath-OutFile,等,让它们的功能就像是指定的字符串-LiteralPath,因为-LiteralPath是不可用Invoke-WebRequest

mkl*_*nt0 7

  • 不幸的是,Invoke-WebRequestInvoke-RestMethod还不支持
    -LiteralPath,因为你的状态,但链接GitHub的问题显示,支持将在未来添加。

  • []字符转义`[and`]以便在将它们解释为带有( )的通配符表达式时按字面处理,不幸的是,由于底部讨论的错误,目前只有一半有效:-Path-FilePath

    • 执行转义确保-Path参数接受路径(命令不再中断)......

    • ...但在创建文件时,错误地将转义表示用作文字文件名 - 请参见底部部分。

目前的解决方法

  • 使用下面详述的转义...
  • ...然后重命名文件以删除不需要的`字符。
# Literal input path.
$literalOutFile = 'file[1].txt'

# Create escaped wildcard-pattern representation that -OutFile accepts.
$escapedOutFile = [WildcardPattern]::Escape($literalOutFile)

# Call Invoke-RestMethod -OutFile with the escaped representation.
'hi' |  Out-File -FilePath $escapedOutFile

# # Rename the resulting file to compensate for the bug discussed below.
# # !! Note how the *escaped* path must be passed to -LiteralPath, because
# # !! the bug causes the output file to be created with the *escaped* name.
Rename-Item -LiteralPath $escapedOutFile ($escapedOutFile -replace '`')
Run Code Online (Sandbox Code Playgroud)

当错误得到修复时,此代码应该继续工作 - 假设您的文件名从不包含嵌入的文字`- 字符。- 尽管Rename-Item呼叫将是空操作。


转义 [文字] 路径以用作通配符模式:

使用以下任何字符串-文字表示形式,最终产生具有逐字内容的相同字符串 file`[1`].txt,当解释为通配符表达式时,它是文字 string的转义等价物file[1].txt

  • 'file`[1`].txt'
  • "file``[1``].txt"
  • file``[1``].txt

要以编程方式创建此转义,请使用:

$literalName = 'file[1].txt'
$escapedName = [WildcardPattern]::Escape($literalName) # -> 'file`[1`].txt'
Run Code Online (Sandbox Code Playgroud)

重要的是目标 cmdlet 将[]作为`-escaped 在它传递给它们的-Path( -FilePath) 参数中进行逐字处理。

如果您使用"..."引号或不带引号的参数(它的行为通常就像包含在 中一样"..."),PowerShell 的字符串解析会妨碍:`还用作可扩展字符串 ( "...") 中的转义字符,因此为了` 通过,您必须逃避它本身,如``

  • 否则像`[inside"..."变成 just [- the `is "eaten" - 因为`[["..."的角度转义,并且转义不需要转义的角色变成了那个角色;简而言之:既"file`[1`].txt"file`[1`].txt变成平原file[1].txt,就好像你从来没有使用过`

相比之下,`字符在带'...'引号的字符串中逐字使用,不需要转义。


许多 cmdlet 的有缺陷的文件创建行为-Path

上面提到的错误- 在文件创建时转义表示被错误地用作文字文件名 -影响大多数cmdlet,不幸的是:也就是说,它们创建文件时意外地保留`了转义模式中的字符,因此通过指定-Path 'file[1].txt'你最终会得到一个名为file`[1`].txt.

幸运的是,大多数 cmdlet 支持-LiteralPath,因此-LiteralPath file[1].txt无论如何使用是更好的选择并避免此错误。

一些受影响的 cmdlet:

  • Invoke-WebRequestInvoke-RestMethod

  • Out-File因此还有重定向操作符>and>>,它们Out-File在幕后有效地调用。

    • 请注意,Set-ContentAdd-Content不会出现此问题。
  • 所有(?) Export-*cmdlet。

  • 其他的?

该错误已在此 GitHub 问题 中报告。