PowerShell中-eq判定文件哈希不同但Write-Host输出一致故障排查
问题原因
你遇到的-eq比对失败是两个独立原因导致的:
- 哈希比对失败的核心问题:
Select-Object Hash返回的是带Hash属性的自定义对象,不是哈希字符串本身。你在控制台看到的@{Hash=xxx}是PowerShell对对象的格式化输出,不是变量的实际值。用-eq比对两个不同的对象实例,哪怕属性值完全一致,也会返回false。 - 直接比对gci输出变量和文件内容失败的问题:
Out-File写入文件时会默认使用系统编码、自动添加换行符、结尾补空行,而gci输出的是字符串数组,直接比对数组和Get-Content读取的内容时,编码、换行格式、结尾空行的差异都会导致比对失败。
修复方法
1. 修正哈希比对逻辑
取哈希值时直接展开属性得到纯字符串,和你之前取FullName的逻辑一致,修改对应代码即可:
# 取旧哈希,添加-ExpandProperty参数直接获取Hash字符串 $lastFile = gci C:\ReportOutputDir | sort LastWriteTime | select -last 1 | Select-Object -ExpandProperty FullName $oldHash = Get-FileHash $lastFile | Select-Object -ExpandProperty Hash # 生成新文件时指定统一编码,避免后续编码差异导致哈希变化 gci -Path C:\FileLists -File -Recurse -Name -Depth 2 | Sort-Object | out-file C:\ReportOutputDir\new_test.txt -Encoding UTF8 # 取新哈希 $newHash = Get-FileHash C:\ReportOutputDir\new_test.txt | Select-Object -ExpandProperty Hash # 此时比对的是两个字符串,结果正常 if ($newHash -eq $oldHash){ 'files are equal' # 相同则删除临时新文件 Remove-Item C:\ReportOutputDir\new_test.txt -Force } else { 'files are not equal' # 不同则可以保留新文件,比如重命名为带时间戳的格式 }
2. 更高效的无临时文件比对方案
如果你不想生成临时文件再比对,可以直接把新的目录列表转成统一格式的字符串,和旧文件内容直接比对:
$lastFile = gci C:\ReportOutputDir | sort LastWriteTime | select -last 1 | Select-Object -ExpandProperty FullName # 读取旧文件内容,统一编码、去除结尾多余空行 $oldContent = (Get-Content $lastFile -Encoding UTF8 -Raw).TrimEnd() # 生成新的目录列表字符串,统一换行格式 $newContent = (gci -Path C:\FileLists -File -Recurse -Name -Depth 2 | Sort-Object) -join "`n" if ($newContent -eq $oldContent) { # 内容无变化,不生成新文件 'content not changed, skip generate new file' } else { # 内容变化,写入新文件 $outputPath = Join-Path C:\ReportOutputDir "$(Get-Date -Format 'yyyyMMddHHmmss').txt" $newContent | Out-File $outputPath -Encoding UTF8 "new report saved to $outputPath" }
内容的提问来源于stack exchange,提问作者myaccountname
相关产品推荐
相关产品推荐

