在 Powershell 中使用 CSV 重命名多个文件
Renaming several files using CSV in Powershell
我有一个特殊的需要,我觉得受困于此..
有些用户会将一些文件放在一个具有多个不同名称的目录中,我需要根据特殊模式重命名它们,以便这些文件被另一个应用程序使用。
示例:
在目录 -> 目标中
file1-dd-mm-yyyy -> 文件 1
文件 2 -> 这个文件 2
flie45224 -> file123
如您所见,这可以是一些变量、日期、ID 等。
目标将始终相同,但源中的文件可能因日期等原因而不同。
所以首先我有 2 个文件,所以我用纯文本编写脚本“如果 test-path blabla 执行此操作,其他文件就会消失”,但现在看来我将有 37 个不同的文件,名称各不相同。所以我考虑过使用 excel sheet(CSV?),但我真的找不到任何帮助来解决这个问题。
目标是将 sheet 作为“模式”,就像您在 'A1' 中找到文件一样,然后像 'A2' 中那样重命名等等...
你们有什么想法吗?
提前致谢:)
似乎有点奇怪,我怀疑您应该可以改用正则表达式模式,但不能在没有看到 csv 内容的情况下说出来。否则试试这个。假设 CSV 有一个名为 First 和 Second 的列 headers,First 匹配文件的基本名称(无扩展名),而 Second 包含您希望它更改为的基本名称。
$csv = Import-Csv -Path c:\filenames.csv
Get-ChildItem -Path c:\temp | %{if($csv.First -contains $_.BaseName){Rename-Item -Path $_.FullName -NewName "$($csv.Second[$csv.First.IndexOf($_.BaseName)]+$_.Extension)"}}
我知道您需要一个包含以下列的 csv:
- A1: regex/pattern 匹配
- A2:转换规则应该是
动态
技巧是使用 scriptblock
如果你想使用像文件名这样的变量。
基本上,您的 csv 将是:
A1;A2
"^file1-\d\d-\d\d-\d\d\d\d$";"file1"
"^file2$";"this$($file.Name)"
"^flie*";"file123"
代码为:
$myRules = Import-Csv "C:\xxx\test.csv" -Delimiter ";"
$files = gci C:\temp\
foreach ($file in $files) {
foreach ($rule in $myRules) {
if ($file.Name -match $rule.A1) {
Write-host "$($file.Name) is matching pattern ""$($rule.A1)"". Applying rename to ""$($rule.A2)"""
$NewScriptBlock = [scriptblock]::Create("rename-item -Path $($file.FullName) -NewName ""$($rule.A2)""")
$NewScriptBlock.Invoke()
}
}
}
之前给的是:
file1-01-02-0344
file2
flie45224
执行期间的输出:
file1-01-02-0344 is matching pattern "^file1-\d\d-\d\d-\d\d\d\d$". Applying rename to "file1"
file2 is matching pattern "^file2$". Applying rename to "this$($file.Name)"
flie45224 is matching pattern "^flie*". Applying rename to "file123"
之后:
file1
thisfile2
file123
说明
第一个foreach
正在解析文件。然后对于这些文件中的每一个,由于 -match $rule.A1
.
,我们正在检查其中一个规则是否匹配
对于第一个示例,您可以使用正则表达式(\d 来匹配数字)。 对于其他情况,我保持简单,因为您没有阐明规则,但这将是您的作业:)
然后在转换规则中,您可以使用文件名变量,如第二个转换规则所示:this$($file.Name)
注意:在当前文件重命名后添加一个标志以离开循环可能是个好主意,以避免不必要的检查并在文件不匹配任何模式时显示消息。
我有一个特殊的需要,我觉得受困于此.. 有些用户会将一些文件放在一个具有多个不同名称的目录中,我需要根据特殊模式重命名它们,以便这些文件被另一个应用程序使用。
示例:
在目录 -> 目标中
file1-dd-mm-yyyy -> 文件 1
文件 2 -> 这个文件 2
flie45224 -> file123
如您所见,这可以是一些变量、日期、ID 等。 目标将始终相同,但源中的文件可能因日期等原因而不同。
所以首先我有 2 个文件,所以我用纯文本编写脚本“如果 test-path blabla 执行此操作,其他文件就会消失”,但现在看来我将有 37 个不同的文件,名称各不相同。所以我考虑过使用 excel sheet(CSV?),但我真的找不到任何帮助来解决这个问题。
目标是将 sheet 作为“模式”,就像您在 'A1' 中找到文件一样,然后像 'A2' 中那样重命名等等... 你们有什么想法吗?
提前致谢:)
似乎有点奇怪,我怀疑您应该可以改用正则表达式模式,但不能在没有看到 csv 内容的情况下说出来。否则试试这个。假设 CSV 有一个名为 First 和 Second 的列 headers,First 匹配文件的基本名称(无扩展名),而 Second 包含您希望它更改为的基本名称。
$csv = Import-Csv -Path c:\filenames.csv
Get-ChildItem -Path c:\temp | %{if($csv.First -contains $_.BaseName){Rename-Item -Path $_.FullName -NewName "$($csv.Second[$csv.First.IndexOf($_.BaseName)]+$_.Extension)"}}
我知道您需要一个包含以下列的 csv:
- A1: regex/pattern 匹配
- A2:转换规则应该是 动态
技巧是使用 scriptblock
如果你想使用像文件名这样的变量。
基本上,您的 csv 将是:
A1;A2
"^file1-\d\d-\d\d-\d\d\d\d$";"file1"
"^file2$";"this$($file.Name)"
"^flie*";"file123"
代码为:
$myRules = Import-Csv "C:\xxx\test.csv" -Delimiter ";"
$files = gci C:\temp\
foreach ($file in $files) {
foreach ($rule in $myRules) {
if ($file.Name -match $rule.A1) {
Write-host "$($file.Name) is matching pattern ""$($rule.A1)"". Applying rename to ""$($rule.A2)"""
$NewScriptBlock = [scriptblock]::Create("rename-item -Path $($file.FullName) -NewName ""$($rule.A2)""")
$NewScriptBlock.Invoke()
}
}
}
之前给的是:
file1-01-02-0344
file2
flie45224
执行期间的输出:
file1-01-02-0344 is matching pattern "^file1-\d\d-\d\d-\d\d\d\d$". Applying rename to "file1"
file2 is matching pattern "^file2$". Applying rename to "this$($file.Name)"
flie45224 is matching pattern "^flie*". Applying rename to "file123"
之后:
file1
thisfile2
file123
说明
第一个foreach
正在解析文件。然后对于这些文件中的每一个,由于 -match $rule.A1
.
对于第一个示例,您可以使用正则表达式(\d 来匹配数字)。 对于其他情况,我保持简单,因为您没有阐明规则,但这将是您的作业:)
然后在转换规则中,您可以使用文件名变量,如第二个转换规则所示:this$($file.Name)
注意:在当前文件重命名后添加一个标志以离开循环可能是个好主意,以避免不必要的检查并在文件不匹配任何模式时显示消息。