PowerShell文件分组排序脚本多目录执行不准确问题求助
问题描述
现有PowerShell脚本在网络驱动器的单个测试目录运行完全正常,但修改为在该驱动器的27个目标目录运行时,结果不准确。脚本核心需求是保留最新文件,判断规则如下:
- 文件未被替代时直接保留;
- 依据文件名第3-4个下划线间的SECTION段数值判断:文件名格式为
NAME_DATE_3位序列_SECTION_SEGMENT_SEQUENCE,比如Name_20240301_001_SectionName_SegmentName_1.pdf和Name_20240301_001_SectionName2_SegmentName_1.pdf,需保留SECTION段数值最大的文件; - 同组文件(匹配NAME、DATE、3位序列、SEGMENT及SECTION非数值部分)中的低数值/无数值文件需移至指定检查目录。
该脚本在本地C盘简单结构、网络驱动器2个目录的模拟环境均运行正常,仅在多目录多文件场景下失效。用户疑惑是否需要为每个目录复制脚本逐个执行,或是有递归执行且保证准确性的方法。
原脚本代码
function Get-SectionNumber { param([string]$fileName) $parts = $fileName -split '_' if ($parts.Count -ge 4) { $sectionPart = $parts[3] $match = [regex]::Match($sectionPart, '(\d+)') if ($match.Success) { return [int]$match.Value } } return $null } function Get-SectionNonNumeric { param([string]$fileName) $parts = $fileName -split '_' if ($parts.Count -ge 4) { $sectionPart = $parts[3] $match = [regex]::Match($sectionPart, '(\D+)') if ($match.Success) { return $match.Value } } return $null } $sourceDirectory = "Drive:\Path1\Path1......" $CheckDeletedDirectory = "Drive:\Path2\Path2......" $files = Get-ChildItem -Path $sourceDirectory -File -Recurse # portion of the section for grouping $groupedFiles = $files | Group-Object { ($_.Name -split '_', 4)[0..2] -join '_' + '_' + (Get-SectionNonNumeric $_.Name) } foreach ($group in $groupedFiles) { $sortedGroup = $group.Group | Sort-Object @{Expression={Get-SectionNumber $_.Name}; Descending=$true} $topFile = $sortedGroup[0] $sortedGroup[1..($sortedGroup.Count - 1)] | ForEach-Object { Move-Item -Path $_.FullName -Destination $catchDirectory -Force Write-Host "Moved $($file.FullName) to $CheckDeletedDirectory" } Write-Host "Retained file: $($topFile.FullName)" }
问题分析与修复方案
1. 原脚本核心问题
- 变量名错误:
Move-Item中使用未定义的$catchDirectory,应为$CheckDeletedDirectory;Write-Host里的$file未定义,需改为$_。 - 分组逻辑遗漏SEGMENT:原分组仅匹配NAME、DATE、3位序列和SECTION非数值部分,未包含SEGMENT,导致不同SEGMENT的文件被错误归为一组。
- 递归场景分组冲突:遍历多子目录时,原脚本仅按文件名分组,会跨目录处理文件,不符合实际需求。
2. 修复后的脚本
function Get-SectionInfo { param([string]$fileName) $parts = $fileName -split '_' $sectionNumber = $null $sectionNonNumeric = $null $segmentPart = $null if ($parts.Count -ge 5) { # 提取SECTION部分的数值和非数值内容 $sectionPart = $parts[3] $numMatch = [regex]::Match($sectionPart, '(\d+)') if ($numMatch.Success) { $sectionNumber = [int]$numMatch.Value } $nonNumMatch = [regex]::Match($sectionPart, '(\D+)') if ($nonNumMatch.Success) { $sectionNonNumeric = $nonNumMatch.Value } # 提取SEGMENT部分 $segmentPart = $parts[4] } return [PSCustomObject]@{ SectionNumber = $sectionNumber SectionNonNumeric = $sectionNonNumeric Segment = $segmentPart } } # 定义所有27个目标目录 $sourceDirectories = @( "Drive:\Path1", "Drive:\Path2", # 继续添加剩余目录... ) $CheckDeletedDirectory = "Drive:\Path2\Path2......" foreach ($dir in $sourceDirectories) { if (-not (Test-Path $dir)) { Write-Warning "目录不存在:$dir" continue } $files = Get-ChildItem -Path $dir -File # 分组键:目录路径 + NAME_DATE_3位序列 + SECTION非数值 + SEGMENT $groupedFiles = $files | Group-Object { $sectionInfo = Get-SectionInfo $_.Name "$($_.Directory.FullName)_$((($_.Name -split '_',4)[0..2]) -join '_')_$($sectionInfo.SectionNonNumeric)_$($sectionInfo.Segment)" } foreach ($group in $groupedFiles) { # 按SectionNumber降序排序,无数值文件默认排最后 $sortedGroup = $group.Group | Sort-Object @{ Expression = { $sectionInfo = Get-SectionInfo $_.Name; $sectionInfo.SectionNumber } Descending = $true Default = 0 } $topFile = $sortedGroup[0] Write-Host "保留文件:$($topFile.FullName)" # 移动其余文件,处理重名情况 $sortedGroup[1..($sortedGroup.Count - 1)] | ForEach-Object { $targetPath = Join-Path $CheckDeletedDirectory $_.Name if (Test-Path $targetPath) { $targetPath = Join-Path $CheckDeletedDirectory "$($_.BaseName)_$([guid]::NewGuid().ToString().Substring(0,8))$($_.Extension)" } Move-Item -Path $_.FullName -Destination $targetPath -Force Write-Host "移动文件:$($_.FullName) -> $targetPath" } } }
3. 关键优化点
- 合并SECTION信息提取:将两个提取函数合并,减少重复逻辑,提升效率。
- 修正分组逻辑:分组时加入目录路径和SEGMENT部分,确保同组文件是同一目录下符合所有规则的文件。
- 修复变量错误:修正了原脚本中的变量名错误。
- 处理文件名重复:移动文件时若目标目录有同名文件,自动添加GUID后缀避免覆盖。
- 批量处理目录:通过数组定义所有目标目录,循环逐个处理,无需复制多份脚本。
内容的提问来源于stack exchange,提问作者Garran Lincoln
相关产品推荐
相关产品推荐

