【问题标题】:Powershell strings are not concatenating properlyPowershell 字符串未正确连接
【发布时间】:2020-10-26 20:12:37
【问题描述】:

所以我有

$Logfilename = "E:\Deployment Logs\20201026 - 1_ProductInfo"
Write-Host $Logfilename
E:\Deployment Logs\20201026 - 1_ProductInfo


$Newname = $Logfilename + ".log"
Write-Host $Newname
.logeployment Logs\20201026 - 1_ProductInfo


Get-Content -Path "E:\Deployment Logs\20201026 - 1_ProductInfo.log"
#returns file normally

但是,当我尝试从变量名运行 Get-Content 时,我收到此错误。这也很奇怪,因为错误消息显示了一个字符串,但上面的 Write-Host .logeployment Logs\20201026 - 1_ProductInfo 显示了一个不同的字符串。

Get-Content -Path $Newname
Get-Content : Illegal characters in path.
At line:1 char:1
+ Get-Content -Path $Newname
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (E:\Deployment L...roductInfo.log:String) [Get-Content], ArgumentException
    + FullyQualifiedErrorId : ItemExistsArgumentError,Microsoft.PowerShell.Commands.GetContentCommand
 
Get-Content : Cannot find path 'E:\Deployment Logs\20201026 - 1_ProductInfo.log' because it does not exist.
At line:1 char:1
+ Get-Content -Path $Newname
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (E:\Deployment L...roductInfo.log:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

我完全不知道这里发生了什么。该文件肯定存在于给定的路径中。我尝试为隐藏的 \r 和 \n 字符添加 .replace 无济于事。我尝试通过Out-String 编写变量内容,然后添加.log,同样的事情发生了。对此有任何解释或解决方法吗?

【问题讨论】:

  • 您的代码看起来很奇怪...您的第一行中缺少引号,我想这是复制粘贴错误?请分别分享您的实际脚本和错误消息。您的路径中可能有多余的空格,或者“-”实际上是一个长破折号等。运行“dir 'E:\Deployment Logs'”时会得到什么输出?
  • running dir E:\Deployment Logs 列出了该文件夹中的所有文件。我已将引号添加到第一行并确认这是复制粘贴错误。
  • 我的意思是:在你的问题中包含输出
  • 如果您尝试连接路径,请使用Join-Path
  • 如果下一行的输出Write-Host $Newname.logeployment Logs\20201026 - 1_ProductInfo,你的代码怎么会是$Newname = $Logfilename + ".log"?因为您的错误是由于 .logeployment Logs\20201026 - 1_ProductInfo 不是有效的文件名。

标签: string powershell filepath illegal-characters


【解决方案1】:

从 cmets 中的对话来看,您的脚本文件在 $Logfilename = "E:\Deployment Logs\20201026 - 1_ProductInfo" 行的字符串末尾有一个隐藏的 Carriage Return 字符(尚未复制到您问题的脚本中)。

当您使用write-host 输出字符串时,回车会将光标移回控制台行的开头,然后继续写入字符串的其余部分。

一个简单的再现是:

PS> "E:\Deployment Logs\20201026 - 1_ProductInfo$([char]0x000D).log"
.logeployment Logs\20201026 - 1_ProductInfo

回车不是文件名中的有效字符,这就是您也看到错误的原因。它看起来也被从错误消息中删除了,所以它只是显示了两个字符串连接的“预期”值:

Get-Content : Cannot find path 'E:\Deployment Logs\20201026 - 1_ProductInfo.log' because it does not exist.

这可能是因为您从其他系统中剪切并粘贴了原始值,并且您在不知情的情况下拾取了隐藏的字符。

要修复它,只需删除$Logfilename = "E:\Deployment Logs\20201026 - 1_ProductInfo" 行中的最后几个字符,然后手动重新键入它们。当您删除字符时,您可能会注意到,有一次您按 delbackspace 似乎什么都不会发生 - 那是您删除非打印字符的时候.

更新

如果 cmets 被删除,我们通过以下测试解决了问题:

PS E:\Deployment Plans> $Logfilename.length
44

PS E:\Deployment Plans> $Newname.length
48

PS> "E:\Deployment Logs\20201026 - 1_ProductInfo".Length
43

PS> "E:\Deployment Logs\20201026 - 1_ProductInfo.log".Length
47

这告诉我们$Logfilename 的末尾可能有一个额外的非打印字符。

下一步:

PS> [System.Text.Encoding]::UTF8.GetBytes("E:\Deployment Logs\20201026 - 1_ProductInfo.log".)
.
.
73
110
102
111

但是

PS> [System.Text.Encoding]::UTF8.GetBytes($Logfilename)
.
.
73
110
102
111
13

所以额外的字符是 UTF 字符 13(十进制),即 U+000D,即回车 - 请参阅 http://www.fileformat.info/info/unicode/char/000d/index.htm

【讨论】:

  • 谢谢!这实际上不是复制粘贴的,而是在我的脚本中。我使用 $Logfilename.Substring(0,$LogfileName.Length-1) 删除了多余的字符