如何在PowerShell中基于单个属性使用Compare-Object并输出全部属性
问题:Compare-Object对比File属性时Hash字段为空,如何显示Hash?
问题背景
现有包含MD5哈希值、文件名(含文件大小和时间戳)的日志文件:
hashlog1.log:
2E331B30A705D462541398874451A955 \steamapps\appmanifest_1036890.acf 798 20230919_003055 D9A3D74B9F48CC599406F1D74D293261 \steamapps\appmanifest_1046030.acf 795 20231021_213325 2C364B22B4866903ED5E3BD9740B9DFA \steamapps\appmanifest_1086410.acf 762 20230413_034326 88D100F2A7FFC2C912B59B45AED9DC48 \steamapps\appmanifest_1091500.acf 925 20231026_112000 2A03A13E570CDA7424216DEF84C958EA \steamapps\appmanifest_1151640.acf 901 20230512_235832
hashlog2.log:
97CAF30C2E1F73ED121F75D947DB29C3 \steamapps\appmanifest_1036890.acf 798 20231122_123455 D9A3D74B9F48CC599406F1D74D293261 \steamapps\appmanifest_1046030.acf 795 20231021_213325 2C364B22B4866903ED5E3BD9740B9DFA \steamapps\appmanifest_1086410.acf 762 20230413_034326 78CF976F8BA64DAF19319E84B8133598 \steamapps\appmanifest_1091500.acf 687 20231122_125522 2A03A13E570CDA7424216DEF84C958EA \steamapps\appmanifest_1151640.acf 901 20230512_235832
通过以下代码生成带列头的对象集合:
$file1=(Get-Content -Path "hashlog1.log") | Select @{N='Hash'; E={($_ -split ' ',2)[0]}},@{N='File'; E={(($_ -split ' ',2)[1])}} $file2=(Get-Content -Path "hashlog2.log") | Select @{N='Hash'; E={($_ -split ' ',2)[0]}},@{N='File'; E={(($_ -split ' ',2)[1])}}
需求是仅基于File属性对比两个集合,但输出结果中要同时包含Hash、File属性。
当前执行以下代码:
Compare-Object $file1 $file2 -Property File | Select Hash,File,SideIndicator
输出结果中Hash属性为空:
Hash File SideIndicator ---- ---- ------------- \steamapps\appmanifest_1036890.acf 798 20231122_123455 => \steamapps\appmanifest_1091500.acf 687 20231122_125522 => \steamapps\appmanifest_1036890.acf 798 20230919_003055 <= \steamapps\appmanifest_1091500.acf 925 20231026_112000 <=
原因分析
当使用Compare-Object仅指定File作为对比属性时,它只会生成包含File和SideIndicator的差异对象,原对象中的Hash属性不会被自动保留,因此直接选择Hash字段会显示为空。
解决方案
在对比出差异后,根据SideIndicator标记,从原集合$file1或$file2中匹配对应的File值,获取关联的Hash,再构建包含完整字段的对象输出:
$file1 = Get-Content -Path "hashlog1.log" | Select @{N='Hash'; E={($_ -split ' ',2)[0]}}, @{N='File'; E={(($_ -split ' ',2)[1])}} $file2 = Get-Content -Path "hashlog2.log" | Select @{N='Hash'; E={($_ -split ' ',2)[0]}}, @{N='File'; E={(($_ -split ' ',2)[1])}} # 对比差异并补充Hash字段 Compare-Object $file1 $file2 -Property File | ForEach-Object { # 根据来源标记获取对应的Hash值 $targetHash = if ($_.SideIndicator -eq '<=') { ($file1 | Where-Object { $_.File -eq $_.File }).Hash } else { ($file2 | Where-Object { $_.File -eq $_.File }).Hash } # 输出包含完整字段的自定义对象 [PSCustomObject]@{ Hash = $targetHash File = $_.File SideIndicator = $_.SideIndicator } }
输出结果
执行后会得到包含Hash的完整差异列表:
Hash File SideIndicator ---- ---- ------------- 2E331B30A705D462541398874451A955 \steamapps\appmanifest_1036890.acf 798 20230919_003055 <= 88D100F2A7FFC2C912B59B45AED9DC48 \steamapps\appmanifest_1091500.acf 925 20231026_112000 <= 97CAF30C2E1F73ED121F75D947DB29C3 \steamapps\appmanifest_1036890.acf 798 20231122_123455 => 78CF976F8BA64DAF19319E84B8133598 \steamapps\appmanifest_1091500.acf 687 20231122_125522 =>
内容的提问来源于stack exchange,提问作者HTWingNut
相关产品推荐
相关产品推荐

