如何加速处理10万条CSV的PowerShell文件夹重命名脚本
PowerShell脚本提速优化方案(10万条CSV+四层文件夹匹配重命名)
原脚本性能瓶颈分析
原脚本的核心问题是重复执行文件系统遍历:每处理一条CSV记录就调用Get-ChildItem扫描一次四层文件夹,10万条记录意味着10万次文件服务器IO操作,这是导致速度极慢的根本原因。此外,逐行逐文件夹的字符串匹配效率偏低,且未处理重复匹配/重命名的情况。
优化思路与实现
优化核心
- 一次性预加载所有目标文件夹:仅执行一次
Get-ChildItem,把所有四层子文件夹的信息存入内存集合,避免重复IO - 预处理CSV数据:提前提取所有需要的
prefix和对应的prepend,对重复的prefix去重,减少无效匹配 - 高效匹配与去重:使用内存集合进行快速匹配,重命名后及时移除已处理的文件夹,避免重复操作
优化后的脚本
$folderPath = "Z:\TopLevelFolder\*\*\*\*" $csvPath = "C:\PathToCSV\file.csv" $count = 0 # 1. 一次性加载所有四层子文件夹,存入内存集合(仅执行一次IO操作) $allFolders = Get-ChildItem -Path $folderPath -Directory -ErrorAction SilentlyContinue | Select-Object FullName, Name # 2. 预处理CSV数据,提取prefix和prepend,同时去重重复的prefix $csvMap = Import-Csv -Path $csvPath | ForEach-Object { $prefix = ($_.Column3 -split ' - ')[0].Trim() $prepend = ($_.Column1 -split '-')[-1].Trim() [PSCustomObject]@{ Prefix = $prefix Prepend = $prepend } } | Group-Object -Property Prefix | ForEach-Object { # 若同一prefix对应多条记录,保留最后一条的prepend(可按需调整逻辑) [PSCustomObject]@{ Prefix = $_.Name Prepend = $_.Group[-1].Prepend } } # 3. 遍历预处理后的映射,在内存中匹配文件夹并执行重命名 foreach ($map in $csvMap) { $prefix = $map.Prefix $prepend = $map.Prepend # 内存中筛选名称包含prefix的文件夹,速度远快于重复扫描磁盘 $matchedFolders = $allFolders | Where-Object { $_.Name -match [regex]::Escape($prefix) } foreach ($folder in $matchedFolders) { $newName = "($prepend) $($folder.Name)" Rename-Item -Path $folder.FullName -NewName $newName -ErrorAction SilentlyContinue if (-not $?) { continue } # 重命名失败则跳过 $count++ Write-Host "已重命名: $($folder.FullName)" # 移除已处理的文件夹,避免后续重复匹配 $allFolders = $allFolders | Where-Object { $_.FullName -ne $folder.FullName } } } Write-Host "$count 个文件夹已重命名"
额外提速建议
- 升级到PowerShell 7+:相比Windows PowerShell,PowerShell 7的集合操作、IO处理性能有大幅提升
- 启用文件服务器缓存:开启本地缓存减少跨网络IO的延迟
- 调整匹配规则:如果
prefix是文件夹名的前缀而非任意包含,将-match改为-like "$prefix*",匹配速度会更快 - 并行处理(可选):若文件夹数量极大,可使用
ForEach-Object -Parallel(PowerShell 7+支持)实现并行匹配,注意重命名操作的线程安全
内容的提问来源于stack exchange,提问作者Nowhere Atoll
相关产品推荐
相关产品推荐

