【问题标题】:Powershell Parameter Seems to Truncate ValuePowershell 参数似乎截断了值
【发布时间】:2019-10-17 23:41:48
【问题描述】:

我有一个在 VSCode 中运行良好的 Powershell 脚本,但在 Powershell 提示中,我遇到了错误。下面是输出。

→ C:\WINDOWS\system32› powershell.exe -file 'D:\Source\Repos\Powershell Scripts\SD-Report-Archive.ps1' -sourcePath 'D:\Archives\' -targetPath 'D:\Archives2\'
D:\Archives\
Get-ChildItem : Cannot find path 'D:\A' because it does not exist.
At D:\Source\Repos\Powershell Scripts\SD-Report-Archive.ps1:25 char:14
+     $files = Get-ChildItem -Recurse -File -Path $sourcePath
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:\A:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

正如您在输出的第 2 行所看到的,我对要发送的参数值进行了写入输出,它是正确的。当我执行 Get-ChildItem 时,它似乎将值截断为 'D:\A',我不知道为什么。

Param(
    [Parameter(Mandatory = $true)]
    [string]$sourcePath,
    [Parameter(Mandatory = $true)]
    [string]$targetPath
)

function Copy-FilesIntoFolders {
    param()

    Write-Output $sourcePath;

    $files = Get-ChildItem -Path $sourcePath -Recurse -File
...
}

【问题讨论】:

  • 如果您从路径中删除尾部反斜杠,您是否会遇到同样的问题?
  • @TheMadTechnician 我没有。非常感谢。我从没想过这会是问题所在。
  • 我刚刚发现这篇文章似乎与将来访问此文章的任何人有关。这可能是发生这种行为的原因。 stackoverflow.com/questions/5079413/…。要考虑的关键语句是“当使用 -File 参数时,powershell.exe 似乎没有完全评估脚本参数。”
  • 从显示的内容来看,它对我有用。也许最好显示整个脚本。
  • @Tim,链接的帖子不相关(这是一个单独的错误);您的问题仅与 PowerShell 损坏的幕后重新引用有关。

标签: powershell get-childitem


【解决方案1】:

Get-ChildItem : 找不到路径“D:\A”,因为它不存在。

这里的反斜杠 (\) 在我看来就像一个转义字符。请尝试使用 \\

【讨论】:

  • 错误消息源自 PowerShell cmdlet。在 PowerShell 代码 \ 中,not 用作转义字符(反引号 (`) 提供该功能)。
【解决方案2】:

在 Windows 上,PowerShell - 必要时 - 重建命令行以调用 外部程序

值得注意的是,大多数外部程序无法通过其 CLI 理解引用的字符串 ('...'),因此 在执行了自己的解析之后,PowerShell 重新引用 使用 引号 ("...") 的结果(字符串化)参数如果它认为有必要

很遗憾,这次重新引用在几个方面损坏

  • 如果参数值不包含 空格,则应用 no 引号。 不带空格但带有特殊字符的值因此可能会中断命令,尤其是在调用另一个 shell(例如 cmd.exe)时。

    • 例如,cmd /c echo 'a&b' 中断,因为 a&b 最终通过 没有 引号,而 &cmd.exe 中具有特殊含义
  • 如果参数嵌入双引号(" 字符。),重新引用不会自动转义它们 用于在 "..." 中的语法正确嵌入或不带引号的文字使用:

    • 例如,foo.exe 'Nat "King" Cole' 被转换为 foo.exe "Nat "King" Cole" - 注意内部 " 字符缺少转义。 - 这会在大多数应用程序解析时产生一个不同的字符串,即Nat King Cole(无双引号)。

    • 您必须手动执行转义除了 PowerShell 自己的转义要求(如果适用):foo.exe 'Nat \"King\" Cole' 或者,使用双引号,
      foo.exe "Nat \`"King\`" Cole"(原文如此)。

  • 与您的情况类似 - 如果参数有空格并以 \ 结尾,则尾随 \ 不会在生成的双引号字符串中转义,它破坏了参数语法:

    • 例如,foo.exe 'a b\' c 变为 foo.exe "a b\" c - 然而,大多数程序 - 包括 PowerShell 自己的 CLI - 将 \" 解释为 转义 " 字符。而不是结束双引号,导致对参数的误解,将其与下一个参数合并以产生
      a b" c

    • 您必须再次手动执行转义,通过 加倍 \
      foo.exe 'a b\\' c

      • 或者,如果参数恰好是一个目录路径,其尾随 \ 是可选的,则只需省略后者。

【讨论】:

  • 所以我想这就是为什么我们必须跳过箍以通过计划任务发送 -Command 参数我发现我必须添加“& 然后双引号所有字符串值,然后关闭末尾双引号。
  • @Tim:如果您从 PowerShell 的外部调用 PowerShell CLI (powershell.exe),则适用不同的规则。对于 -File,您必须使用 double 引用的字符串,但将尾随 \ 加倍的要求仍然适用。是的,将一段 PowerShell 代码传递给 -Command 是一种可行的解决方法,尽管在行为上存在差异,特别是在如何确定退出代码方面 - 请参阅 stackoverflow.com/a/57443822/45375
  • 感谢您的参考。那篇文章解释了很多。
猜你喜欢
  • 1970-01-01
  • 2012-03-08
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
相关资源
最近更新 更多