PowerShell中使用Import-Csv提取列唯一值并存储为变量的问题
解决CSV唯一值提取与PDF批量重命名问题
问题说明
有一个包含art列的CSV文件,该列存在5个唯一值,需要将这些值分别存入变量,用于批量重命名对应的PDF文件。当前PowerShell代码仅能正确获取第一个值,后续变量无法拿到对应数据,需优化实现方式。
相关CSV数据
sequence art last first address city st zip 1 3S Doe John 123 Any Street AnyTown 6 3S Doe John 128 Any Street AnyTown 2 OG Dow Jane 124 Any Street AnyTown 7 OG Dow Jane 129 Any Street AnyTown 3 OGF Cool Joe 125 Any Street AnyTown 8 OGF Cool Joe 130 Any Street AnyTown 4 SLV Cool Carol 126 Any Street AnyTown 9 SLV Cool Carol 131 Any Street AnyTown 5 SMP Bravo Johnny 127 Any Street AnyTown 10 SMP Bravo Johnny 132 Any Street AnyTown
现有问题代码
If (Test-Path D:\mhWork\_Auto\_Print\c1478_tpl_snap\data\Art_cProofs.csn){ $source=Get-ChildItem "D:\mhWork\_Auto\_Print\c1478_tpl_snap\data\Art_cProofs.csn" | select -Last 1 $artTag = 'D:\mhWork\_Auto\_Print\c1478_tpl_snap\data\Art_cProofs.csn' $artTag1 = Import-Csv $artTag | Select-Object -ExpandProperty art -First 1 $artTag2 = Import-Csv $artTag | Select-Object -ExpandProperty art -Second 2 $artTag3 = Import-Csv $artTag | Select-Object -ExpandProperty art -Third 3 $artTag4 = Import-Csv $artTag | Select-Object -ExpandProperty art -Fourth 4 $artTag5 = Import-Csv $artTag | Select-Object -ExpandProperty art -Fifth 5 $JobID = "TPL_" + ($aJobNum) If (Test-Path cProofs0001.pdf){ Rename-Item cProofs0001.pdf "$($JobID)_$($artTag1)_cProofs.pdf"} If (Test-Path cProofs0002.pdf){ Rename-Item cProofs0002.pdf "$($JobID)_$($artTag2)_cProofs.pdf"} If (Test-Path cProofs0003.pdf){ Rename-Item cProofs0003.pdf "$($JobID)_$($artTag3)_cProofs.pdf"} If (Test-Path cProofs0004.pdf){ Rename-Item cProofs0004.pdf "$($JobID)_$($artTag4)_cProofs.pdf"} If (Test-Path cProofs0005.pdf){ Rename-Item cProofs0005.pdf "$($JobID)_$($artTag5)_cProofs.pdf"} }
预期重命名效果
cProofs0001.pdf → 123456_TPL_3S_cProofs.pdf cProofs0002.pdf → 123456_TPL_OG_cProofs.pdf cProofs0003.pdf → 123456_TPL_OGF_cProofs.pdf cProofs0004.pdf → 123456_TPL_SLV_cProofs.pdf cProofs0005.pdf → 123456_TPL_SMP_cProofs.pdf
问题分析
- 参数错误:
Select-Object仅支持-First参数,不存在-Second/-Third等参数,导致后续变量无法获取值。 - 重复读取文件:多次调用
Import-Csv读取同一文件,效率低下。 - 冗余代码:硬编码多个
If语句,重复逻辑过多,不易维护。
优化后的实现代码
$csvPath = 'D:\mhWork\_Auto\_Print\c1478_tpl_snap\data\Art_cProofs.csn' # 检查CSV文件是否存在 if (Test-Path $csvPath) { # 一次性导入CSV,按sequence升序排序后提取唯一的art值 $uniqueArtTags = Import-Csv $csvPath | Sort-Object { [int]$_.sequence } | Select-Object -ExpandProperty art -Unique # 定义JobID(需确保$aJobNum已正确赋值,示例中假设为123456) $aJobNum = "123456" $JobID = "{0}_TPL_" -f $aJobNum # 循环处理每个PDF文件 for ($index = 0; $index -lt $uniqueArtTags.Count; $index++) { $pdfOldName = "cProofs{0:D4}.pdf" -f ($index + 1) if (Test-Path $pdfOldName) { $pdfNewName = "{0}{1}_cProofs.pdf" -f $JobID, $uniqueArtTags[$index] # 测试阶段可添加-WhatIf参数预览重命名效果,确认无误后移除 Rename-Item $pdfOldName $pdfNewName } } }
代码说明
- 一次性读取处理CSV:仅调用一次
Import-Csv,避免重复IO操作。 - 按顺序提取唯一值:通过
Sort-Object按sequence的数值排序,再用-Unique获取不重复的art值,保证顺序与预期一致。 - 循环批量处理:用
for循环遍历唯一值数组,动态生成PDF文件名,简化代码逻辑,避免重复代码。 - 格式化文件名:使用
-f格式化运算符生成规范的文件名,提升代码可读性。
内容的提问来源于stack exchange,提问作者cnjfo672
相关产品推荐
相关产品推荐

