Get-ChildItem获取LastWriteTime异常:毫秒差异致Compare-Object失败求助
解决PowerShell中文件时间毫秒差异导致Compare-Object误判的问题
这个问题其实挺常见的——系统在读取文件时间戳时,偶尔会因为底层文件系统特性或读取精度问题,出现毫秒级的微小波动,哪怕文件本身根本没修改。除了转字符串,这里有几个更靠谱的方案:
1. 截断时间戳到秒级(或更低精度)
你可以在获取时间的时候直接去掉毫秒部分,只保留到秒的精度。这样即使读取时毫秒有波动,也不会影响比对结果。修改你的Get-ChildItem命令,对时间属性做处理:
Get-ChildItem -Path 'C:\Windows\Microsoft.NET\assembly\GAC_MSIL' -Include *.dll -Recurse | Select-Object @{Label="AssemblyName";Expression={$_.Name}}, @{Label="Size"; Expression={$_.Length}}, @{label="Version";expression={$_.VersionInfo.ProductVersion ?? "NULL"}}, @{Label="CreationTime"; Expression={$_.CreationTime.AddMilliseconds(-$_.CreationTime.Millisecond)}}, @{Label="LastWriteTimeUtc"; Expression={$_.LastWriteTimeUtc.AddMilliseconds(-$_.LastWriteTimeUtc.Millisecond)}}
这里用AddMilliseconds(-$_.CreationTime.Millisecond)直接把毫秒部分归零,得到的时间只有秒级精度,比对时就不会因为毫秒差异触发误判了。
2. 用文件哈希值替代时间戳判断文件修改
时间戳并不是判断文件是否真被修改的最可靠方式(比如有些工具会修改时间戳但不改动内容),如果你的核心需求是检测文件内容变化,直接计算文件哈希值会更准确:
# 定义获取程序集信息+哈希的脚本块 $getAssemblyInfo = { Get-ChildItem -Path 'C:\Windows\Microsoft.NET\assembly\GAC_MSIL' -Include *.dll -Recurse | Select-Object @{Label="AssemblyName";Expression={$_.Name}}, @{Label="Size"; Expression={$_.Length}}, @{label="Version";expression={$_.VersionInfo.ProductVersion ?? "NULL"}}, @{Label="FileHash"; Expression={(Get-FileHash $_.FullName -Algorithm SHA256).Hash}} } # 第一次获取基准数据 $oldObject = & $getAssemblyInfo # 等待5分钟 Start-Sleep -Seconds 300 # 获取新数据 $newObject = & $getAssemblyInfo # 比对哈希值(和其他关键属性) Compare-Object $oldObject $newObject -Property AssemblyName, FileHash
这种方式下,只有当文件内容真的改变时,哈希值才会变化,完全避开了时间戳的精度问题。
3. 在Compare-Object中自定义时间比对逻辑
如果一定要保留完整时间戳,但比对时忽略毫秒差异,可以在Compare-Object里用脚本块处理时间属性:
Compare-Object $oldobject $newObject -Property Name, @{ Name = 'LastWriteTimeUtc' Expression = { $_.LastWriteTimeUtc.AddMilliseconds(-$_.LastWriteTimeUtc.Millisecond) } }
这种方式是在比对阶段才处理时间戳,不用修改原始对象的属性,适合需要保留原始时间数据但比对时忽略毫秒的场景。
补充一句:如果是NTFS文件系统,文件的LastWriteTime理论上应该是稳定的,但某些特殊场景(比如文件被多个进程访问、系统缓存刷新)可能出现微小精度偏差,截断到秒级基本能解决大部分这类问题。
内容的提问来源于stack exchange,提问作者chaitu t
相关产品推荐
相关产品推荐

