比较对象返回错误值
Compare-Object is returning the wrong value
我正在处理 PowerShell 脚本,Compare-Object
cmdlet 不是我所期望的 returning。我不会把整个脚本放在这里,但这是总体思路:
$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
return不出所料。但是,使用下面的示例:
$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
它会 return 这个:
InputObject SideIndicator
----------- -------------
@{Name=file5.dat; Length=25137; LastWriteTimeUtc=1/3/2018 8:07:51 AM} =>
它确实检测到两个对象之间存在差异,但它始终只是 return 最后一行,而不是不同的实际记录。如果有两个更改的文件,则 return 是最后两行。如果我将 "-property Name"
添加到 Compare-Object
,它 return 是正确的文件名,但我还需要查找大小和写入时间的差异。我可以使用 Export-Csv
将两个对象写回一个文件,然后在这些文件的 Get-Content
上使用 运行 Compare-Object
,效果很好,但我不知道我想将两个文件写入磁盘,因为此作业每分钟将 运行在不同的文件夹上执行数百次。
编辑: 根据其中一个建议,我也尝试了 Compare-Object ... -Property Name, Length, LastWriteTimeUtc
,当我这样做时,它 return 中的每个项目两个对象,或者 100% 不匹配。
我做错了什么?
指定要用来比较对象的属性:
Compare-Object $knownFileObject $currentFileObject -Property Name, Length, LastWriteTimeUtc
您还需要确保您比较的是同一事物。您的方法的问题是 FileInfo
对象的 LastWriteTimeUtc
属性 是一个 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 格式)存储时间戳,并对目录列表中的时间戳使用相同的格式。顺便说一句,不需要对数组进行排序,因此您可以放弃该步骤。
$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
我正在处理 PowerShell 脚本,Compare-Object
cmdlet 不是我所期望的 returning。我不会把整个脚本放在这里,但这是总体思路:
$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
return不出所料。但是,使用下面的示例:
$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
它会 return 这个:
InputObject SideIndicator ----------- ------------- @{Name=file5.dat; Length=25137; LastWriteTimeUtc=1/3/2018 8:07:51 AM} =>
它确实检测到两个对象之间存在差异,但它始终只是 return 最后一行,而不是不同的实际记录。如果有两个更改的文件,则 return 是最后两行。如果我将 "-property Name"
添加到 Compare-Object
,它 return 是正确的文件名,但我还需要查找大小和写入时间的差异。我可以使用 Export-Csv
将两个对象写回一个文件,然后在这些文件的 Get-Content
上使用 运行 Compare-Object
,效果很好,但我不知道我想将两个文件写入磁盘,因为此作业每分钟将 运行在不同的文件夹上执行数百次。
编辑: 根据其中一个建议,我也尝试了 Compare-Object ... -Property Name, Length, LastWriteTimeUtc
,当我这样做时,它 return 中的每个项目两个对象,或者 100% 不匹配。
我做错了什么?
指定要用来比较对象的属性:
Compare-Object $knownFileObject $currentFileObject -Property Name, Length, LastWriteTimeUtc
您还需要确保您比较的是同一事物。您的方法的问题是 FileInfo
对象的 LastWriteTimeUtc
属性 是一个 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 格式)存储时间戳,并对目录列表中的时间戳使用相同的格式。顺便说一句,不需要对数组进行排序,因此您可以放弃该步骤。
$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