如何使用 PowerShell 比较文件夹和数组中的子字符串?
How to compare substrings within a folder and an array with PowerShell?
我有一个包含 100,000 个文件(图片)的文件夹,这些文件(图片)由 UPC 代码(8 到 14 位数字)后跟下划线和其他数字命名:
000012345678_00_1
我在 word 文档中有一个包含 20,000 个唯一 UPC 代码的列表(用逗号分隔),这些代码应该与这些图片中的五分之一相匹配(我在 Excel table 中也有这个列表).
000000000000, 000000000001, 000000000011
我正在尝试做的是在我的数组(20,000 个元素列表)和我的文件夹中的文件之间找到匹配项,以便从文件夹中仅提取那 20,000 张图片。
我首先将文件名截断到“__”,以便只获取文件名的相关部分:
$FName = ($File -split '_')[0]
为了使事情变得更难,我还需要向数组中的元素添加一个通配符“*”,因为文件名开头的一些额外“0”可能已被添加并且不存在于我们的大批。例如数组“05713901”中的这个UPC就是指这个文件名“00005713901_00.png”;所以要找到匹配项,我将不得不使用 "like" 运算符。
然后当我找到这些匹配项时,我只需使用 Move-Item 到新文件夹或子文件夹。
这是我开始编写的代码,但没有任何结果:
$Directory = "C:path_to_my_folder";
$AllFiles = Get-ChildItem $Directory
$FileNames = New-Object System.Collections.ArrayList;
foreach($File in $AllFiles)
{
$FName = ($File -split '_')[0]
$FileNames.Add($FName)
}
$Upc = Get-Content C:\path_to_my_word.docx
Compare-Object $FileNames $Upc
您无法使用 Get-Content
读取 docx
文件,即使可以读取,Compare-Object
也无法正常工作,因为您的 word 文件是 UPC 上的列表-用逗号分隔的代码(powershell 中的单个 string
),而 $FileNames
是一个数组(多个对象)。
将 UPC 代码从 excel 复制到记事本,这样您就可以得到一个简单的文本文件,每行一个代码,类似于此示例。
UPC.txt - 内容:
000000000000
000000000001
000000000011
....
每个 运行 100.000 个文件通过 20.000 -like
个测试循环需要很长时间。我会创建一个正则表达式模式来查找末尾带有下划线的任一代码。例如:
$Directory = "C:\path_to_my_folder";
$AllFiles = Get-ChildItem $Directory
#Generate regex that matches 00001_ or 00002_ etc. Trimming leading and trailing whitespace just to be safe.
$regex = ((Get-Content -Path "c:\UPC.txt") | ForEach-Object { "$($_.Trim())_" }) -join '|'
#Get files that match
$AllFiles | Where-Object { $_.Name -match $regex } | ForEach-Object {
#Do something, ex. Move file.
Move-Item -Path $_.FullName -Dest C:\Destination
}
或者干脆
$AllFiles | Where-Object { $_.Name -match $regex } | Move-Item -Destination "C:\Destination"
将您的 UPC 代码保存为纯文本文件。正如 Frode F. 建议的那样,将它们从 Excel 复制到记事本可能是最简单的方法。保存该列表。然后我们将该列表加载到 PowerShell 中,对于每个文件,我们将像您一样在下划线和 trim 任何前导零处拆分,然后检查它是否在已知代码列表中。使用 Move-Item
移动已知 UPC 列表中的任何文件
#Import Known UPC List
$UPCList = Get-Content C:\Path\To\UPCList.txt
#Remove Leading Zeros From List
$UPCList = $UPCList | ForEach{$_.TrimStart('0')}
$Directory = "C:path_to_my_folder"
Get-ChildItem $Directory | Where{$_.Name.Split('_')[0].TrimStart('0') -in $UPCList} | Move-Item -Dest C:\Destination
我有一个包含 100,000 个文件(图片)的文件夹,这些文件(图片)由 UPC 代码(8 到 14 位数字)后跟下划线和其他数字命名:
000012345678_00_1
我在 word 文档中有一个包含 20,000 个唯一 UPC 代码的列表(用逗号分隔),这些代码应该与这些图片中的五分之一相匹配(我在 Excel table 中也有这个列表).
000000000000, 000000000001, 000000000011
我正在尝试做的是在我的数组(20,000 个元素列表)和我的文件夹中的文件之间找到匹配项,以便从文件夹中仅提取那 20,000 张图片。
我首先将文件名截断到“__”,以便只获取文件名的相关部分:
$FName = ($File -split '_')[0]
为了使事情变得更难,我还需要向数组中的元素添加一个通配符“*”,因为文件名开头的一些额外“0”可能已被添加并且不存在于我们的大批。例如数组“05713901”中的这个UPC就是指这个文件名“00005713901_00.png”;所以要找到匹配项,我将不得不使用 "like" 运算符。
然后当我找到这些匹配项时,我只需使用 Move-Item 到新文件夹或子文件夹。
这是我开始编写的代码,但没有任何结果:
$Directory = "C:path_to_my_folder";
$AllFiles = Get-ChildItem $Directory
$FileNames = New-Object System.Collections.ArrayList;
foreach($File in $AllFiles)
{
$FName = ($File -split '_')[0]
$FileNames.Add($FName)
}
$Upc = Get-Content C:\path_to_my_word.docx
Compare-Object $FileNames $Upc
您无法使用 Get-Content
读取 docx
文件,即使可以读取,Compare-Object
也无法正常工作,因为您的 word 文件是 UPC 上的列表-用逗号分隔的代码(powershell 中的单个 string
),而 $FileNames
是一个数组(多个对象)。
将 UPC 代码从 excel 复制到记事本,这样您就可以得到一个简单的文本文件,每行一个代码,类似于此示例。
UPC.txt - 内容:
000000000000
000000000001
000000000011
....
每个 运行 100.000 个文件通过 20.000 -like
个测试循环需要很长时间。我会创建一个正则表达式模式来查找末尾带有下划线的任一代码。例如:
$Directory = "C:\path_to_my_folder";
$AllFiles = Get-ChildItem $Directory
#Generate regex that matches 00001_ or 00002_ etc. Trimming leading and trailing whitespace just to be safe.
$regex = ((Get-Content -Path "c:\UPC.txt") | ForEach-Object { "$($_.Trim())_" }) -join '|'
#Get files that match
$AllFiles | Where-Object { $_.Name -match $regex } | ForEach-Object {
#Do something, ex. Move file.
Move-Item -Path $_.FullName -Dest C:\Destination
}
或者干脆
$AllFiles | Where-Object { $_.Name -match $regex } | Move-Item -Destination "C:\Destination"
将您的 UPC 代码保存为纯文本文件。正如 Frode F. 建议的那样,将它们从 Excel 复制到记事本可能是最简单的方法。保存该列表。然后我们将该列表加载到 PowerShell 中,对于每个文件,我们将像您一样在下划线和 trim 任何前导零处拆分,然后检查它是否在已知代码列表中。使用 Move-Item
#Import Known UPC List
$UPCList = Get-Content C:\Path\To\UPCList.txt
#Remove Leading Zeros From List
$UPCList = $UPCList | ForEach{$_.TrimStart('0')}
$Directory = "C:path_to_my_folder"
Get-ChildItem $Directory | Where{$_.Name.Split('_')[0].TrimStart('0') -in $UPCList} | Move-Item -Dest C:\Destination