PowerShell中对比两个HashSet结果为空:跨共享文件名匹配异常排查
问题排查:HashSet求交集返回空结果的修复
我用两个HashSet分别存储不同文件共享的文件名,目标是找出两者的共同文件名存入第三个HashSet $setDiff,要求结果无重复且支持任一集合为空的场景。但实际运行时,明明存在匹配的文件名,却偶尔返回空结果。
初始化代码
$setOrig = New-Object System.Collections.Generic.HashSet[System.String] $setOrigNames = New-Object System.Collections.Generic.HashSet[System.String] $setArchived = New-Object System.Collections.Generic.HashSet[System.String] $setArchivedNames = New-Object 'System.Collections.Generic.HashSet[System.String]' $setDiff = New-Object System.Collections.Generic.HashSet[System.String] $origNamePathPair = New-Object 'System.Collections.Generic.Dictionary[string,string]' $archNamePathPair = New-Object 'System.Collections.Generic.Dictionary[string,string]'
原核心逻辑代码
$setOrig = Get-ChildItem -Path $_.FullName -Recurse -Include("*.png")$setArchived | ForEach-Object { $archNamePathPair[$_.BaseName] = $setArchived[$i], $i++ } $idx = 0 $setOrig | ForEach-Object { $origNamePathPair[$_.BaseName] = $setOrig[$idx], $idx++ } $setOrigNames = $setOrig | ForEach-Object {$_.BaseName} $setArchivedNames = $setArchived | ForEach-Object {$_.BaseName} $hash1 = [System.Collections.Generic.HashSet[string]]::new( [string[]] ($setOrigNames), [System.StringComparer]::InvariantCulture) $hash2 = [System.Collections.Generic.HashSet[string]]::new( [string[]] ($setArchivedNames), [System.StringComparer]::InvariantCulture) $setDiff = @( $hash2.Where{ $hashset1.Contains($_) } )
问题根源
- 变量名拼写错误:核心逻辑中使用了未定义的
$hashset1,正确变量名应为$hash1,这直接导致无法匹配元素 - 语法混乱:
Get-ChildItem语句拼接错误,$setOrig和$setArchived未被正确初始化 - HashSet访问错误:HashSet不支持索引访问(如
$setArchived[$i]),此类操作会返回空值或引发异常 - 类型不符合需求:最终将
$setDiff赋值为数组,而非要求的HashSet类型
修复后的核心逻辑
# 正确获取源文件集合(需确保$_指向目标目录) $setOrig = Get-ChildItem -Path $_.FullName -Recurse -Include "*.png" | Select-Object -ExpandProperty FullName # 替换$archivedPath为你的归档文件共享路径 $setArchived = Get-ChildItem -Path $archivedPath -Recurse -Include "*.png" | Select-Object -ExpandProperty FullName # 构建文件名-路径映射(修复索引访问问题) $setOrig | ForEach-Object { $file = Get-Item $_ $origNamePathPair[$file.BaseName] = $file.FullName } $setArchived | ForEach-Object { $file = Get-Item $_ $archNamePathPair[$file.BaseName] = $file.FullName } # 提取文件名集合 $setOrigNames = $setOrig | ForEach-Object { (Get-Item $_).BaseName } $setArchivedNames = $setArchived | ForEach-Object { (Get-Item $_).BaseName } # 创建指定字符串比较规则的HashSet $hash1 = [System.Collections.Generic.HashSet[string]]::new( [string[]]$setOrigNames, [System.StringComparer]::InvariantCulture ) $hash2 = [System.Collections.Generic.HashSet[string]]::new( [string[]]$setArchivedNames, [System.StringComparer]::InvariantCulture ) # 求交集并保持HashSet类型 $hash2.Where({ $hash1.Contains($_) }) | ForEach-Object { [void]$setDiff.Add($_) }
简化优化方案
直接利用HashSet内置的IntersectWith方法求交集,代码更简洁高效:
# 初始化HashSet并传入文件名集合 $hash1 = [System.Collections.Generic.HashSet[string]]::new($setOrigNames, [System.StringComparer]::InvariantCulture) $hash2 = [System.Collections.Generic.HashSet[string]]::new($setArchivedNames, [System.StringComparer]::InvariantCulture) # 直接求交集,结果存入$hash1 $hash1.IntersectWith($hash2) # 赋值给目标HashSet $setDiff = $hash1
内容的提问来源于stack exchange,提问作者Newborn
相关产品推荐
相关产品推荐

