首先,强制性警告:除非您将命令行存储为单个字符串某处并且您完全控制或信任字符串的内容,Invoke-Expression should generally be avoided。
您发现 PowerShell 如何处理由直接连接的带引号和不带引号的部分组成的复合标记不一致。
具体来说,参数 "C:\Test Folder With Blanks":/zzz 意外地分成两部分(即,作为两个单独的参数传递)。
解决方法是引用整个参数,即
"C:\Test Folder With Blanks:/zzz"
注意:我假设 docker 实际上并不需要在其参数中引用 部分,这是不应该的;但是,Windows 上有一些备受瞩目的 CLI,尤其是 msiexec。
或者,使用包含在(...) 中的表达式 来组成您的字符串;例如
("C:\Test Folder With Blanks" + ':/zzz')
在这种情况下没有充分的理由这样做,但如果您需要在字符串的一部分 ("...") 而在另一部分 ('...') 中不需要字符串插值,这可能会有所帮助。
一般注意事项:
-
与 cmd.exe 以及与 POSIX 兼容的 shell(例如 bash)相比,PowerShell 有几个附加元字符,尤其是 @987654337 @(在令牌的开头)、{ / } 和 ;。因此,您不能总是期望为这些 shell 编写的命令行在 PowerShell 中按原样工作。
-
从 PowerShell 7.2.2 开始,将参数传递给 外部程序(例如 docker)对于具有 嵌入 " 字符的参数而言从根本上被破坏了和 空字符串 参数 - 请参阅 this answer。
从 PowerShell 7.2.2 开始,不一致的一般模式如下:
如果是参数:
-
以一个引用标记开头 - 无论是单引号 (
'...') 还是双引号 ("...") -
-
and 在结束引号之后有其他字符,
第一个这样的字符开始一个单独的参数。
例如"foo":bar / "foo"=bar / "foo"'bar' 分别作为单独的参数传递 foo 和 :bar / foo 和 =bar / foo 和 bar。
换句话说:
# OK: First token is unquoted.
PS> cmd /c echo foo"bar"'baz'last
foobarbazlast
# !! BROKEN: First token is quoted.
# !! Because each successive token is quoted too,
# !! each becomes its own argument.
PS> cmd /c echo 'foo'"bar"'baz'last
foo bar baz last
GitHub issue #6467 讨论了这种不一致;但是,它已被关闭,因为令人惊讶的是,这种行为是经过设计考虑的。
如果第一个标记未引用,这不会发生;但是,有相关错误以未引用标记开头,类似地将参数分成两部分,这与它们看起来像命名参数 到 PowerShell(这是一个 PowerShell 概念,在调用外部程序时不适用):