Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 在多个文件中搜索字符串,然后使用该字符串重命名文件_Powershell - Fatal编程技术网

Powershell 在多个文件中搜索字符串,然后使用该字符串重命名文件

Powershell 在多个文件中搜索字符串,然后使用该字符串重命名文件,powershell,Powershell,我正在尝试创建一个PowerShell脚本,该脚本将搜索一系列.txt文件(.hl7文件,确切地说,但它们只是txt文件)并在这些文件中搜索,以查看它们是否包含四位数。如果文件确实包含该四位数字,则应使用添加到原始文件名前面的字符串重命名该文件。因此test.hl7应该变成8000\u test.hl7,如果该文件包含这4位数字 经过一天的疯狂搜索和挖掘,这是我所能想到的最好的: $AccountIDs = ("8155", "8156", "8428") $Path = "C:\Users\T

我正在尝试创建一个PowerShell脚本,该脚本将搜索一系列.txt文件(.hl7文件,确切地说,但它们只是txt文件)并在这些文件中搜索,以查看它们是否包含四位数。如果文件确实包含该四位数字,则应使用添加到原始文件名前面的字符串重命名该文件。因此test.hl7应该变成8000\u test.hl7,如果该文件包含这4位数字

经过一天的疯狂搜索和挖掘,这是我所能想到的最好的:

$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)
    }
}
我得到了一些有趣的结果。我目前在该邮件文件夹中有四个测试文件,testtest2test3skibbidybop。第一个测试将正确更改为8156_测试。但是,其他文件不会被触碰。现在,当我将test的文件名更改为ttest时,脚本完全跳过该文件,然后分别将test2test3重命名为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
    }