求助:基于PowerShell实现批量文件重命名结合SQL查询功能
可配置源/目标目录的批量文件处理工具解决方案
需求明确
- 支持配置源目录(待处理文件所在)和目标目录(处理后文件输出)
- 批量读取源目录下所有文件(含子目录)
- 文件名解析规则:去除扩展名后,按第一个下划线分割取前半部分作为
prodId - 通过SQL查询匹配
prodId获取对应SKU值 - 文件处理规则:将文件复制到目标目录,并重命名为
原文件名主体__sku-<SKU值>.扩展名(示例:prodId--IBZ.ext→prodId--IBZ__sku-AJSJSJSJSJ.ext)
完善后的PowerShell代码
以下是修正并优化后的代码,解决了原代码的逻辑错误、参数引用错误等问题:
function Invoke-FileBatchProcessor { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$SourceDirectory, # 源目录参数 [Parameter(Mandatory=$true)] [string]$TargetDirectory, # 目标目录参数 [string]$SqlServer = ".", # SQL服务器地址,默认本地 [string]$Database = "YourDatabaseName", # 替换为实际数据库名 [string]$TableName = "tbl" # 替换为实际表名 ) # 确保目标目录存在,不存在则创建 if (-not (Test-Path -Path $TargetDirectory)) { New-Item -Path $TargetDirectory -ItemType Directory | Out-Null } # 1. 获取源目录下所有文件(含子目录) $files = Get-ChildItem -Path $SourceDirectory -Recurse -File # 2. 批量提取所有prodId,减少SQL查询次数 $prodIds = @() foreach ($file in $files) { # 解析prodId:去扩展名后按第一个下划线分割取前半部分 $nameWithoutExt = $file.BaseName $prodId = $nameWithoutExt -split "_", 2 | Select-Object -First 1 $prodIds += $prodId } # 去重避免重复查询 $uniqueProdIds = $prodIds | Select-Object -Unique # 3. 从SQL查询所有匹配的prodId与SKU映射 $sqlQuery = @" SELECT prodId, sku FROM $TableName WHERE prodId IN ('$($uniqueProdIds -join "','")') "@ $connectionString = "Data Source=$SqlServer;Integrated Security=SSPI;Initial Catalog=$Database" $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString) $cmd = New-Object System.Data.SqlClient.SqlCommand($sqlQuery, $connection) try { $connection.Open() $reader = $cmd.ExecuteReader() # 构建prodId到SKU的哈希表,方便快速查找 $skuMap = @{} while ($reader.Read()) { $skuMap[$reader["prodId"]] = $reader["sku"] } } catch { Write-Error "SQL查询失败:$_" return } finally { $connection.Close() } # 4. 批量处理文件:复制并重命名 foreach ($file in $files) { # 重新解析当前文件的prodId $nameWithoutExt = $file.BaseName $prodId = $nameWithoutExt -split "_", 2 | Select-Object -First 1 # 检查是否找到对应SKU if ($skuMap.ContainsKey($prodId)) { $sku = $skuMap[$prodId] # 构建新文件名:原主体__sku-<SKU>.扩展名 $newFileName = "$($file.BaseName)__sku-$($sku)$($file.Extension)" $targetPath = Join-Path -Path $TargetDirectory -ChildPath $newFileName # 复制文件到目标目录(避免覆盖原文件) Copy-Item -Path $file.FullName -Destination $targetPath -Force Write-Verbose "已处理文件:$($file.Name) → $newFileName" } else { Write-Warning "未找到prodId '$prodId' 对应的SKU,跳过文件:$($file.Name)" } } } # 调用示例:替换为实际目录和数据库信息 # Invoke-FileBatchProcessor -SourceDirectory "C:\SourceFiles" -TargetDirectory "C:\ProcessedFiles" -Database "YourDB"
代码关键修正点
- 修复了原代码中错误引用
$scriptPath的问题,改用传入的SourceDirectory参数 - 优化SQL查询逻辑:批量提取并去重prodId,一次查询所有映射关系,提升处理效率(适合数千文件场景)
- 新增目标目录自动创建逻辑
- 修正文件处理逻辑:遍历文件而非SQL结果,实现正确的复制重命名
- 增加错误处理和日志提示,方便排查问题
免费替代方案
如果PowerShell仍不符合需求,可选择以下两种方案:
C# 方案思路
- 使用
Directory.EnumerateFiles遍历源目录文件 - 用
Path.GetFileNameWithoutExtension和字符串分割解析prodId - 使用
SqlConnection批量查询SKU映射 - 用
File.Copy实现文件复制并重命名,可借助并行处理提升速度(适合大文件/超大量文件场景)
Node.js 方案思路
- 使用
fs.promises.readdir或第三方库glob遍历文件 - 用
path.parse解析文件名,分割字符串获取prodId - 使用
mssql或tedious库连接SQL Server查询SKU - 用
fs.promises.copyFile实现文件复制重命名,异步处理适合高并发场景
内容的提问来源于stack exchange,提问作者AlphaG33k
相关产品推荐
相关产品推荐

