Compare-Object返回错误的值

时间:2018-01-24 22:17:28

标签: powershell compareobject

我正在使用PowerShell脚本而Compare-Object cmdlet没有返回我期望的内容。我不会把整个脚本放在这里,但这是一般的想法:

$knownFiles = Import-Csv -Path "C:\knownfiles.csv"
$currentFiles = Get-ChildItem -Path "\\file\share"
$knownFileObject = $knownFiles |
                   Select-Object -Property Name, Length, LastWriteTimeUTC |
                   Sort-Object -Property Name
$currentFileObject = $currentFiles |
                     Select-Object -Property Name, Length, LastWriteTimeUTC |
                     Sort-Object -Property Name

所以现在,我有两个排序的PSCustomObjects,包含一组文件的名称,长度和上次写入时间。这是我无法弄清楚的。

如果对象相同,Compare-Object不会返回任何内容,如预期的那样。但是,使用以下示例:

$knownFileObject看起来像这样:

Name          Length     LastWriteTimeUtc
----          ------     ----------------
file1.dat     38988     1/1/2018 8:04:57 AM
file2.dat     7182      1/2/2017 8:03:24 AM
file4.dat     1026      1/3/2017 8:04:20 AM
file5.dat     25137     1/3/2018 8:07:51 AM

$currentFileObject看起来像这样:

Name          Length     LastWriteTimeUtc
----          ------     ----------------
file1.dat     38988     1/1/2018 8:04:57 AM
file2.dat     7182      1/2/2017 8:03:24 AM
file3.dat     1026      1/2/2018 8:04:30 AM
file4.dat     1026      1/3/2017 8:04:20 AM
file5.dat     25137     1/3/2018 8:07:51 AM

如果我跑

Compare-Object -ReferenceObject $knownFileObject -DifferenceObject $currentFileObject

它会返回:

InputObject                                                            SideIndicator
-----------                                                            -------------
@{Name=file5.dat; Length=25137; LastWriteTimeUtc=1/3/2018 8:07:51 AM}  =>

它肯定会检测到两个对象之间存在差异,但它总是只返回最后一行,而不是实际记录的不同。如果有两个已更改的文件,则返回最后两行。如果我向"-property Name"添加Compare-Object,它会返回正确的文件名,但我还需要查找大小和写入时间的差异。我可以使用Export-Csv将两个对象写回文件,然后在这些文件的Compare-Object上运行Get-Content,这样做效果很好,但我不知道想要将两个文件写入磁盘,因为这个作业将在不同文件夹上每分钟运行数百次。

编辑:根据其中一条建议,我还尝试了Compare-Object ... -Property Name, Length, LastWriteTimeUtc,当我这样做时,它会返回两个对象中的每个项目,或100%不匹配

我做错了什么?

1 个答案:

答案 0 :(得分:2)

指定要比较对象的属性:

Compare-Object $knownFileObject $currentFileObject -Property Name, Length, LastWriteTimeUtc

您还需要确保比较同样的事情。您的方法的问题是LastWriteTimeUtc对象的FileInfo属性是DateTime对象,其具有亚秒级精度:

PS C:\> Get-Date| Format-List *

DisplayHint : DateTime
DateTime    : Donnerstag, 25. Januar 2018 16:31:07
Date        : 25.01.2018 00:00:00
Day         : 25
DayOfWeek   : Thursday
DayOfYear   : 25
Hour        : 16
Kind        : Local
Millisecond : 268          ← this here
Minute      : 31
Month       : 1
Second      : 7
Ticks       : 636524946672682859
TimeOfDay   : 16:31:07.2682859
Year        : 2018

但CSV中的时间戳是精度限制为秒的字符串,因此原始时间戳和存储时间戳之间可能存在微小差异。

在您的情况下,最好的方法是以定义的格式(例如,长ISO格式)存储时间戳,并使用相同的格式作为目录列表中的时间戳。 BTW不需要对数组进行排序,因此您可以放弃该步骤。

$saved   = Import-Csv 'C:\knownfiles.csv' |
           Select-Object Name, Length, LastWriteTimeUtc
$current = Get-ChildItem '\\server\share' |
           Select-Object Name, Length,
               @{n='LastWriteTimeUtc';e={$_.LastWriteTimeUtc.ToString('s')}}

Compare-Object $saved $current -Property Name, Length, LastWriteTimeUtc