我的公司有数百万份 pdf 格式的旧报告。它们通常以以下格式命名:2018-09-18 - ReportName.pdf
我们需要提交这些文件的组织现在要求我们以这种格式命名文件:Report Name - 2018-09.pdf
我需要将文件名的前 7 个字符移到末尾。我在想可能有一个简单的代码来执行此任务,但我无法弄清楚。谁能帮我。
谢谢!
我的公司有数百万份 pdf 格式的旧报告。它们通常以以下格式命名:2018-09-18 - ReportName.pdf
我们需要提交这些文件的组织现在要求我们以这种格式命名文件:Report Name - 2018-09.pdf
我需要将文件名的前 7 个字符移到末尾。我在想可能有一个简单的代码来执行此任务,但我无法弄清楚。谁能帮我。
谢谢!
警告:
正如jazzdelightsme指出的那样,鉴于您要从日期中删除日期组件,所需的重命名操作可能会导致名称冲突;例如,2018-09-18 - ReportName.pdf
并且2018-09-19 - ReportName.pdf
会产生相同的文件名,Report Name - 2018-09.pdf
.
无论哪种方式,我都假设重命名操作是在原始文件的副本上执行的。或者,您可以在枚举原件时在其他地方创建具有新名称的副本,但这样做的好处是它会在名称冲突的情况下报告错误。Copy-Item
Rename-Item
Get-ChildItem -Filter *.pdf | Rename-Item -NewName {
$_.Name -replace '^(\d{4}-\d{2})-\d{2} - (.*?)\.pdf$', '$2 - $1.pdf'
} -WhatIf
-WhatIf
预览重命名操作;删除它以执行实际重命名。
添加-Recurse
到Get-CildItem
调用以处理整个目录子树。
的使用-Filter
是可选的,但它可以加快处理速度。
一个脚本块( { ... }
) 被传递给Rename-Item
's-NewName
参数,它可以动态重命名从使用字符串转换(替换)表达式$_
接收到的每个输入文件 () 。Get-ChildItem
该-replace
运算符使用一个正则表达式(正则表达式)作为它的第一个操作数,根据模式执行字符串替换;在这里,正则表达式分解如下:
^(\d{4}-\d{2})
匹配名称的2018-09
开头(_ _ _捕获组。^
(...)
$1
(.*?)
捕获文件名的其余部分,不包括捕获组中的扩展名$2
。
?
after.*
使子表达式non-greedy ,这意味着它也会给后续的子表达式一个匹配的机会,而不是尝试匹配尽可能多的字符(这是默认行为,称为greedy)。\.pdf$
匹配.pdf
末尾 ( ) 的文件扩展名 ( $
) - 请注意大小写无关紧要。.
被转义为\.
,因为它的意思是在这里按字面意思匹配(不转义,.
匹配单行字符串中的任何单个字符)。
$2 - $1.pdf
是替换字符串,它安排捕获组以所需形式捕获的内容。
请注意,名称与正则表达式不匹配的任何文件都将被单独放置,因为-replace
如果不匹配,则操作员会传递输入字符串,Rename-Item
如果新名称与旧名称相同,则不执行任何操作。
Get-ChildItem
使用一些正Rename-Item
则表达式并且可以做到:
Get-ChildItem -Path "C:\temp" | foreach {
$newName = $_.Name -replace '(^.{7}).*?-\s(.*?)\.(.*$)','$2 - $1.$3'
$_ | Rename-Item -NewName $newName
}
正则表达式
'(^.{7}).*?-\s(.*?)\.(.*$)'
/$2 - $1.$3
(^.{7})
匹配前 7 个字符.*?-\s
匹配任何字符,直到(包括)第一个找到的-
字符(空格破折号空格)(.*?)\.
匹配任何内容,直到找到第一个点 ( . )(.*$)
在这种情况下匹配文件扩展名$2 - $1.$3
将所有内容按更改后的顺序放在一起如果文件名中有多个点 ( . ),这将无法正常工作。
这应该有效(添加了一些测试数据):
$test = '2018-09-18 - ReportName.pdf','2018-09-18 - Other name.pdf','other pattern.pdf','2018-09-18 - double.extension.pdf'
$test | % {
$match = [Regex]::Match($_, '(?<Date>\d{4}-\d\d)-\d\d - (?<Name>.+)\.pdf')
if ($match.Success) {
"$($match.Groups['Name'].Value) - $($match.Groups['Date'].Value).pdf"
} else {
$_
}
}
像这样的东西-
Get-ChildItem -path $path | Rename-Item -NewName {$_.BaseName.Split(' - ')[-1] + ' - ' + $_.BaseName.SubString(0,7) + $_.Extension} -WhatIf
解释 -
Split
将根据参数分隔文件名,-
并[-1]
告诉 PowerShell 选择最后一个分隔值。SubString(0,7)
将从文件的第一个字符开始选择 7 个字符BaseName
。-WhatIf
以应用重命名。