【问题标题】:Need to batch add characters to filenames using Powershell需要使用 Powershell 将字符批量添加到文件名中
【发布时间】:2019-12-11 21:15:29
【问题描述】:

我有一系列文件都命名为:

PRT14_WD_14220000_1.jpg

我需要在最后一个下划线之后和数字之前添加两个零,这样它看起来像 PRT14_WD_14220000_001.jpg

我试过了”

(dir) | rename-Item -new { $_.name -replace '*_*_*_','*_*_*_00' }

感谢任何帮助。

【问题讨论】:

    标签: powershell filenames


    【解决方案1】:

    与您尝试的最接近的是这个。在正则表达式中,通配符是.*。并且括号会分组以供稍后使用美元符号数字参考。

    dir *.jpg | rename-Item -new { $_.name -replace '(.*)_(.*)_(.*)_','$1_$2_$3_00' } -whatif
    
    What if: Performing the operation "Rename File" on target "Item: C:\users\admin\foo\PRT14_WD_14220000_1.jpg Destination: C:\users\admin\foo\PRT14_WD_14220000_001.jpg".
    

    好的,当您想要最大两个零填充的数字时,这是我的看法。 $num 必须是我想要的 .tostring() 方法的整数。

    dir *.jpg | rename-item -newname { $a,$b,$c,$num = $_.basename -split '_'
      $num = [int]$num
      $a + '_' + $b + "_" + $c + '_' + $num.tostring('000') + '.jpg'
    } -whatif
    
    

    【讨论】:

    • 这行得通。谢谢你。跟进问题,我的名字的结尾总是需要 3 个字符。如果我最后的起始整数是两位数,我将如何处理?我会有一些文件有一个数字,而另一些文件有两个。所以如果它以'_11.jpg'开头,我需要它是'_011.jpg',但如果它是'_5.jpg',我需要它是'_005.jpg'?
    • 我会以完全不同的方式使用 -split 和 .tostring()。您能否将其添加到问题中?
    【解决方案2】:

    以下假设您的.BaseName 的最后一部分将始终需要添加两个零。它是做什么的......

    • 伪造你从Get-Item/Get-ChildItem获得的fileinfo对象
      将其替换为适当的 cmdlet。 [咧嘴一笑]
    • 使用_作为分割目标将.BaseName分割成多个部分
    • 在上述拆分的最后部分添加两个零
    • 将部分合并为$NewBaseName
    • 获取.FullName 并将原始BaseName 替换为$newBaseName
    • 显示新文件名

    您仍然需要进行重命名,但这很直接。 [咧嘴一笑]

    这是代码...

    # fake getting a file info object
    #    in real life, use Get-Item or Get-ChildItem
    $FileInfo = [System.IO.FileInfo]'PRT14_WD_14220000_1.jpg'
    
    $BNParts = $FileInfo.BaseName.Split('_')
    $BNParts[-1] = '00{0}' -f $BNParts[-1]
    $NewBasename = $BNParts -join '_'
    
    $NewFileName = $FileInfo.FullName.Replace($FileInfo.BaseName, $NewBaseName)
    
    $NewFileName
    

    输出 = D:\Data\Scripts\PRT14_WD_14220000_001.jpg

    【讨论】:

      【解决方案3】:

      -replace operatorregexes (regular expressions) 上运行,而不是 wildcard expressons,例如 *(单独),这是您尝试使用的。

      在概念上更直接的方法是将替换重点放在字符串的结尾

      Get-ChildItem | # `dir` is a built-in alias for Get-ChildItem`
        Rename-Item -NewName { $_.Name -replace '(?<=_)[^_]+(?=\.)', '00$&' } -WhatIf
      

      注意:上面命令中的-WhatIf common parameter预览操作。一旦您确定该操作会执行您想要的操作,请删除 -WhatIf

      • (?&lt;=_)[^_]+(?=\.) 匹配非_ 字符的非空运行 (+)。 ([^_]) 前面是 _ ((?&lt;=_),后面是文字 . ((?=\.)),不包括前面的 _ 和后面的 . 来自 捕获的内容 匹配((?&lt;=...)(?=...) 是非捕获环顾断言)。

        • 简而言之:这匹配并捕获最后一个 _ 之后和文件扩展名开始之前的字符。
      • 00$&amp; 替换与 00 匹配的内容,然后是匹配捕获的内容 ($&amp;)。


      在后续评论中,您提到不仅要盲目插入00,还希望0-left-pad 最后一个_ 后面的数字为3 位数,无论如何这个数字可能是。

      PowerShell [Core] 6.1+中,可以这样实现:

      Get-ChildItem |
        Rename-Item -NewName { 
          $_.Name -replace '(?<=_)[^_]+(?=\.)', { $_.Value.PadLeft(3, '0') } 
        } -WhatIf
      
      • 脚本块 ({ ... }) 作为替换操作数接收每个匹配项作为存储在自动变量 $_ 中的 Match 实例,其 .Value 属性包含捕获的文本。

      • 在捕获的文本 0-left-pad 上调用 .PadLeft(3, '0') 将其填充到 3 位并输出结果,这将替换手头的正则表达式匹配。

      快速演示:

      PS> 'PRT14_WD_14220000_1.jpg' -replace '(?<=_)[^_]+(?=\.)', { $_.Value.PadLeft(3, '0') }
      PRT14_WD_14220000_001.jpg # Note how '_1.jpg' was replaced with '_001.jpg'
      

      早期的 PowerShell 版本中,您必须直接使用 .NET [regex] 类型的 .Replace() method,其工作原理基本相同:

      Get-ChildItem |
        Rename-Item -NewName { 
          [regex]::Replace($_.Name, '(?<=_)[^_]+(?=\.)', { param($m) $m.Value.PadLeft(3, '0') }) 
        } -WhatIf
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-10
        • 1970-01-01
        • 2020-12-26
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多