1

我的公司有数百万份 pdf 格式的旧报告。它们通常以以下格式命名:2018-09-18 - ReportName.pdf

我们需要提交这些文件的组织现在要求我们以这种格式命名文件:Report Name - 2018-09.pdf

我需要将文件名的前 7 个字符移到末尾。我在想可能有一个简单的代码来执行此任务,但我无法弄清楚。谁能帮我。

谢谢!

4

4 回答 4

1

警告

  • 正如jazzdelightsme指出的那样,鉴于您要从日期中删除日期组件,所需的重命名操作可能会导致名称冲突;例如,2018-09-18 - ReportName.pdf并且2018-09-19 - ReportName.pdf会产生相同的文件名,Report Name - 2018-09.pdf.

  • 无论哪种方式,我都假设重命名操作是在原始文件的副本上执行的。或者,您可以在枚举原件时在其他地方创建具有新名称的副本,但这样做的好处是会在名称冲突的情况下报告错误Copy-ItemRename-Item

Get-ChildItem -Filter *.pdf | Rename-Item -NewName { 
  $_.Name -replace '^(\d{4}-\d{2})-\d{2} - (.*?)\.pdf$', '$2 - $1.pdf' 
} -WhatIf

-WhatIf 预览重命名操作;删除它以执行实际重命名。
添加-RecurseGet-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如果新名称与旧名称相同,则不执行任何操作。

于 2018-09-19T15:09:22.743 回答
0

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将所有内容按更改后的顺序放在一起

如果文件名中有多个点 ( . ),这将无法正常工作。

于 2018-09-19T13:26:23.543 回答
0

这应该有效(添加了一些测试数据):

$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 {
        $_
    }
}
于 2018-09-19T13:28:44.063 回答
0

像这样的东西-

Get-ChildItem -path $path | Rename-Item -NewName {$_.BaseName.Split(' - ')[-1] + ' - ' + $_.BaseName.SubString(0,7) + $_.Extension} -WhatIf

解释 -

  1. Split将根据参数分隔文件名,-[-1]告诉 PowerShell 选择最后一个分隔值。
  2. SubString(0,7)将从文件的第一个字符开始选择 7 个字符BaseName
  3. 删除-WhatIf以应用重命名。
于 2018-09-19T13:30:01.123 回答