Powershell 在多个文件中搜索字符串,然后使用该字符串重命名文件
我正在尝试创建一个PowerShell脚本,该脚本将搜索一系列.txt文件(.hl7文件,确切地说,但它们只是txt文件)并在这些文件中搜索,以查看它们是否包含四位数。如果文件确实包含该四位数字,则应使用添加到原始文件名前面的字符串重命名该文件。因此test.hl7应该变成8000\u test.hl7,如果该文件包含这4位数字 经过一天的疯狂搜索和挖掘,这是我所能想到的最好的:Powershell 在多个文件中搜索字符串,然后使用该字符串重命名文件,powershell,Powershell,我正在尝试创建一个PowerShell脚本,该脚本将搜索一系列.txt文件(.hl7文件,确切地说,但它们只是txt文件)并在这些文件中搜索,以查看它们是否包含四位数。如果文件确实包含该四位数字,则应使用添加到原始文件名前面的字符串重命名该文件。因此test.hl7应该变成8000\u test.hl7,如果该文件包含这4位数字 经过一天的疯狂搜索和挖掘,这是我所能想到的最好的: $AccountIDs = ("8155", "8156", "8428") $Path = "C:\Users\T
$AccountIDs = ("8155", "8156", "8428")
$Path = "C:\Users\ThatsMe\Downloads\messages"
$Files = (Get-ChildItem $Path -Filter "*.hl7")
for ($i = 0; $i -le $Files.Length; $i++) {
if (Get-Content $Files[$i].FullName | Select-String -Pattern $AccountIDs[$i]) {
Rename-Item $Files[$i].FullName -NewName (($AccountIDs[$i]) + "_" + $Files[$i].Name)
}
}
我得到了一些有趣的结果。我目前在该邮件文件夹中有四个测试文件,test、test2、test3和skibbidybop。第一个测试将正确更改为8156_测试。但是,其他文件不会被触碰。现在,当我将test的文件名更改为ttest时,脚本完全跳过该文件,然后分别将test2和test3重命名为8156_test2(这是不正确的)和8428_test3skibbidybop从不被触摸
当然,还有来自PowerShell的错误消息:
Select-String : Cannot bind argument to parameter 'Pattern' because it is null.
At line:6 char:61
+ if (Get-Content $Files[$i].FullName | Select-String -Pattern <<<< $AccountIDs[$i]) {
+ CategoryInfo : InvalidData: (:) [Select-String], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SelectStringCommand
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:6 char:16
+ if (Get-Content <<<< $Files[$i].FullName | Select-String -Pattern $AccountIDs[$i]) {
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand
这是我现在收到的错误:
C:\> C:\Users\ThatsMe\Downloads\messages\changename.ps1
Cannot index into a null array.
At C:\Users\ThatsMe\Downloads\messages\changename.ps1:8 char:38
+ $id = $_.Group.Matches[ <<<< 0].Groups[0].Value
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
What if: Performing operation "Rename File" on Target "Item:
C:\Users\ThatsMe\Downloads\messages\test.hl7 Destination:
C:\Users\ThatsMe\Downloads\messages\_".
Cannot index into a null array.
At C:\Users\ThatsMe\Downloads\messages\changename.ps1:8 char:38
+ $id = $_.Group.Matches[ <<<< 0].Groups[0].Value
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
What if: Performing operation "Rename File" on Target "Item:
C:\Users\ThatsMe\Downloads\messages\test3.hl7 Destination:
C:\Users\ThatsMe\Downloads\messages\_".
C:\>C:\Users\ThatsMe\Downloads\messages\changename.ps1
无法索引到空数组中。
在C:\Users\ThatsMe\Downloads\messages\changename.ps1:8 char:38
+$id=$\u.Group.Matches[您得到的错误是由两个错误引起的,其中一个是经典错误。PowerShell数组是基于零的,这意味着数组的最后一个索引比其元素数少一个: 此外,您不能对两个不同的数组(
$Files
和$AccountIDs
)使用相同的索引变量,除非您确保两个数组具有相同的长度,或者至少第二个数组($AccountIDs
)的元素多于用于确定最大索引的元素($Files
)。如果$AccountIDs
的元素少于$Files
,则您的代码最终将尝试访问超出$AccountIDs
上限的索引。此外,您可能希望检查每个文件中是否有$AccountIDs
中的所有数字。执行此操作需要使用第二个索引变量的嵌套循环e
话虽如此,但这将使问题变得更加复杂。您只需将ID放在一个单独的文件中,然后将文件列表导入
Select String
,以对照该正则表达式进行检查:
$pattern = '\b(8155|8156|8428)\b'
Get-ChildItem $Path -Filter '*.hl7' |
Select-String -Pattern $pattern |
Group-Object Path |
ForEach-Object {
$id = $_.Group.Matches[0].Groups[0].Value
$filename = $_.Group.Filename | Select-Object -First 1
Rename-Item -Path $_.Name -NewName "${id}_${filename}" -WhatIf
}
正则表达式\b(8155 | 8156 | 8428)\b
匹配任何给定的数字。\b
将匹配限制为单词边界,以避免匹配81552或842893等数字
Group Object
语句确保重命名文件的唯一性(这样,如果在文件中找到多个匹配项,则不会多次尝试重命名文件)
匹配[0]。组[0]。值
为每个文件提取第一个匹配的第一个捕获组的值
Select Object-First 1
确保即使在一个文件中找到多个匹配项,也只有一个文件名字符串,而不是它们的数组
验证重命名操作是否正常工作后,请删除-WhatIf
开关,并重新运行整个语句以实际重命名文件
编辑:对于PowerShell v2,您需要稍微调整组处理,因为该版本不支持
您得到的错误是由两个错误引起的,其中一个是经典错误。PowerShell数组是基于零的,这意味着数组的最后一个索引比其元素数少一个: 此外,您不能对两个不同的数组(
$Files
和$AccountIDs
)使用相同的索引变量,除非您确保两个数组具有相同的长度,或者至少第二个数组($AccountIDs
)的元素多于用于确定最大索引的元素($Files
)。如果$AccountIDs
的元素少于$Files
,则您的代码最终将尝试访问超出$AccountIDs
上限的索引。此外,您可能希望检查每个文件中是否有$AccountIDs
中的所有数字。执行此操作需要使用第二个索引变量的嵌套循环e
话虽如此,但这将使问题变得更加复杂。您只需将ID放在一个单独的文件中,然后将文件列表导入
Select String
,以对照该正则表达式进行检查:
$pattern = '\b(8155|8156|8428)\b'
Get-ChildItem $Path -Filter '*.hl7' |
Select-String -Pattern $pattern |
Group-Object Path |
ForEach-Object {
$id = $_.Group.Matches[0].Groups[0].Value
$filename = $_.Group.Filename | Select-Object -First 1
Rename-Item -Path $_.Name -NewName "${id}_${filename}" -WhatIf
}
正则表达式\b(8155 | 8156 | 8428)\b
匹配任何给定的数字。\b
将匹配限制为单词边界,以避免匹配81552或842893等数字
Group Object
语句确保重命名文件的唯一性(这样,如果在文件中找到多个匹配项,则不会多次尝试重命名文件)
匹配[0]。组[0]。值
为每个文件提取第一个匹配的第一个捕获组的值
Select Object-First 1
确保即使在一个文件中找到多个匹配项,也只有一个文件名字符串,而不是它们的数组
验证重命名操作是否正常工作后,请删除-WhatIf
开关,并重新运行整个语句以实际重命名文件
编辑:对于PowerShell v2,您需要稍微调整组处理,因为该版本不支持
你的回答让我有了更深刻的认识,并帮助我理解了逻辑
for ($i = 0; $i -lt $Files.Length; $i++) {
$pattern = '\b(8155|8156|8428)\b'
Get-ChildItem $Path -Filter '*.hl7' |
Select-String -Pattern $pattern |
Group-Object Path |
ForEach-Object {
$id = $_.Group.Matches[0].Groups[0].Value
$filename = $_.Group.Filename | Select-Object -First 1
Rename-Item -Path $_.Name -NewName "${id}_${filename}" -WhatIf
}
Get-ChildItem $Path -Filter '*.hl7' |
Select-String -Pattern $pattern |
Group-Object Path |
ForEach-Object {
$id = $_.Group | Select-Object -Expand Matches -First 1 |
ForEach-Object { $_.Groups[0].Value }
$filename = $_.Group | Select-Object -Expand Filename -First 1
Rename-Item -Path $_.Name -NewName "${id}_${filename}" -WhatIf
}