“$xyz"和“写主机“$xyz""给出不同的输出 [英] "$xyz" and "Write-Host "$xyz"" giving different output

查看:83
本文介绍了“$xyz"和“写主机“$xyz""给出不同的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在对一个位置(一个原始文件夹)中的所有文件进行哈希处理,并将这些哈希值写入一个变量,然后对另一个位置(一个目标文件夹)中的所有文件执行相同操作:

$origin = Get-ChildItem .\Test1 |获取-FileHash |格式表 - 属性哈希 -HideTableHeaders$destination = Get-ChildItem .\Test2 |获取-FileHash |格式表 - 属性哈希 -HideTableHeaders

然后我将它们与比较对象进行比较:

Compare-Object $origin $destination

现在在我的测试中我故意有偏差,所以当上面的代码没有返回任何差异时,我知道我有问题.

然后我发现,如果我执行以下操作,则哈希值不存在:

<前>PS> 写主机$origin"Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

但是,如果我只是输入以下内容并按回车键,那么哈希值就会出现(就像我想要的那样):

<前>PS> $origin6B86B273FF34FCE19D6B804EFF5A3F5747ADA4EAA22F1D49C01E52DDB7875B4BD4735E3A265E16EEE03F59718B9B5D03019C07D8B6C51F90DA3A666EEC13AB354E07408562BEDB8B60CE05C1DECFE3AD16B72230967DE01F640B7E4729B49FCE

我假设当我使用 Compare-Object 时,我的变量没有像我预期的那样呈现哈希值.

有谁知道发生了什么或有什么建议吗?这用于确保文件从原始位置移动到目标位置(这是我正在处理的脚本中的一项检查).我保持这个纯粹的 PowerShell,这意味着没有 xcopyrobocopy.

解决方案

重新使用 Format-TableCompare-Object 创建输入集合:

仅使用 Format-* cmdlet 进行显示格式;如果数据必须以编程方式处理,切勿使用它们.

Format-* cmdlet 输出格式说明,而不是数据 - 请参阅这个答案.

因此:

  • 省略来自输入集合定义命令的 Format-Table 调用:

$origin=Get-ChildItem .\Test1 |获取文件哈希$destination=Get-ChildItem .\Test2 |获取文件哈希

  • 然后将属性名称传递给Compare-Object:

Compare-Object $origin $destination -Property Path, Hash

注意需要通过路径和哈希进行比较,以确保只比较同名的文件.

顺便说一句:如果您没有指定-Property,默认情况下对象将通过它们的.ToString()进行比较值 - 并且由于 Get-FileHash 输出的 Microsoft.PowerShell.Commands.FileHashInfo 实例只会字符串化为那个非常类型名称(不管它们的特定属性值),不会发现差异.

<小时>

至于 $originWrite-Host $orgin:

  • 只执行 $origin 隐含地类似于执行 Write-Output $origin - 它写入成功输出流(参见 about_Redirection),默认进入控制台.

  • Write-Host,相比之下,服务于Write-Output不同的目的代码>:

    • 直接写入控制台[1]绕过 PowerShell 的成功输出流,从而也绕过其通常的格式.其主要目的是将状态消息、交互式提示消息...写入显示器 - 而不是输出数据.

    • Write-Host 自身应用输出格式,但只能通过简单的.ToString() 字符串化,这通常会产生无用的(仅类型名称)表示,就像您的情况一样.

请参阅此答案,了解有关Write-Output 之间差异的更多信息>写主机.

<小时>

[1] 从技术上讲,从 PowerShell 版本 5 开始,Write-Host 输出通过 information 输出流(编号 6code>),但它的主要目的仍然是写入显示,而不是输出数据.

I am hashing all the files in one location, an origin folder, and writing the hashes to a variable and then doing the same to all the files in another location, a destination folder:

$origin = Get-ChildItem .\Test1 | Get-FileHash | Format-Table -Property Hash -HideTableHeaders
$destination = Get-ChildItem .\Test2 | Get-FileHash | Format-Table -Property Hash -HideTableHeaders

Then I am comparing them with Compare-Object like so:

Compare-Object $origin $destination

Now in my test I purposefully have deviations, so when the above code returned no differences I knew I had a problem.

Then I found out that if I do the following, that the hash values arn't there:

PS> Write-Host "$origin"
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

However, if I just type the following and press enter, then the hash values are present (like I want):

PS> $origin

6B86B273FF34FCE19D6B804EFF5A3F5747ADA4EAA22F1D49C01E52DDB7875B4B
D4735E3A265E16EEE03F59718B9B5D03019C07D8B6C51F90DA3A666EEC13AB35
4E07408562BEDB8B60CE05C1DECFE3AD16B72230967DE01F640B7E4729B49FCE

I am assuming when I use Compare-Object, that my variables are not presenting the hash values like I expected.

Does anyone know what is going on or have any recommendations? This is being used to ensure files are moved from an origin location to a destination location (this is one check in a script I'm working on). I am keeping this purely PowerShell, which means no xcopy or robocopy.

解决方案

Re use of Format-Table to create the input collections for Compare-Object:

Only ever use Format-* cmdlets for display formatting; never use them if data must be programmatically processed.

Format-* cmdlets output formatting instructions, not data - see this answer.

Therefore:

  • Omit the Format-Table calls from your input-collection definition commands:

$origin=Get-ChildItem .\Test1 | Get-FileHash
$destination=Get-ChildItem .\Test2 | Get-FileHash

  • Then pass the names of the properties to compare the objects by to Compare-Object:

Compare-Object $origin $destination -Property Path, Hash

Note the need to compare by both path and hash, to make sure that only files of the same name are compared.

As an aside: If you didn't specify -Property, the objects would by default be compared by their .ToString() value - and since the Microsoft.PowerShell.Commands.FileHashInfo instances output by Get-FileHash only ever stringify to that very type name (irrespective of their specific property values), no differences would be found.


As for $origin vs. Write-Host $orgin:

  • Just executing $origin is implicitly like executing Write-Output $origin - it writes to the success output stream (see about_Redirection), which by default goes to the console.

  • Write-Host, by contrast, serves a different purpose than Write-Output:

    • It writes directly to the console[1], bypassing PowerShell's success output stream and thereby also its usual formatting. Its primary purpose is to write status messages, interactive prompt messages, ... to the display - as opposed to outputting data.

    • Write-Host itself applies output formatting, but only by simple .ToString() stringification, which often yields unhelpful (type name-only) representations, as in your case.

See this answer for more information about the differences between Write-Output and Write-Host.


[1] Technically, since PowerShell version 5, Write-Host output reaches the console via the information output stream (number 6), but its primary purpose is still to write to the display as opposed to outputting data.

这篇关于“$xyz"和“写主机“$xyz""给出不同的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆