Powershell 批量重新编号文件而不更改原始名称

huangapple go评论74阅读模式
英文:

Powershell Renumbering Files in Bulk Without Replacing the Original Name

问题

在PowerShell中,我正在尝试重命名大约2,500个文件。但是,有些文件需要删除,因为它们是重复的。现在还剩下2,400个文件,但这些文件的命名不是按顺序的(例如,DATE_Photo001_NAME,DATE_Photo003_NAME)。

我一直在尝试在一次操作中处理日期和照片编号,但是这些照片跨越了多个日期,我只是想简化操作。

ls |
  Rename-Item -NewName { $_.Name -replace "Photo(\d+)", { "Photo{0:D3}" -f $matches[1] } }

这会不断引发错误,因为文件名中的“???”自然是无效的。我以为占位符会像命令提示符一样工作,因为我之前使用命令提示符,然后才开始使用PowerShell。欢迎任何帮助,如果有更简单的方法,请告诉我!

英文:

In Powershell I am trying to rename ~2,500 files. However, some needed to be deleted as they were duplicates. Now 2,400 remain, but these files are not numbered sequentially (ie DATE_Photo001_NAME, DATE_Photo003_NAME)

I have been using the following to do the dates and the photo #'s in one pass, however, these photos span multiple dates and I'm just trying to streamline it.

ls |
  Rename-Item -NewName {$_.name -replace "Photo???",("Photo{0:d3}" -f  {1},$nr++)}

This keeps throwing me an error because the "???" is naturally invalid in a file name. I thought that the placeholder would work the same as the command prompt which I used before diving into Powershell. Any help is welcome and if there is an easier way to do this let me know!

答案1

得分: 1

请将您传递给 -replace 的正则表达式(regex)设置为仅在前面有 _Photo 并且后面有 _ 的一系列数字(\d+)匹配,并用新的序列号替换这些数字:

$nr = @{ Value = 1 }
Get-ChildItem -File |
  Rename-Item -NewName { 
    $_.Name -replace '(?<=_Photo)\d+(?=_)', ($nr.Value++).ToString('D3') 
  } -WhatIf

请注意:

  • 辅助哈希表(hashtable@{ Value = 1 } 用于包含序列号,这是出于技术原因必要的:延迟绑定脚本块 在调用者的 作用域中运行 - 有关背景信息,请参阅此答案

  • 传递给 Get-ChildItem-File 开关(在Windows上的内置别名之一是 ls)限制处理仅限于 文件,而不包括目录。

  • 传递给 -replace 的正则表达式使用了正向 lookaround assertions ((?<=...)(?=...)),以确保感兴趣的模式位于数字运行之前和之后,但不包括在被捕获的内容中。

  • 所需的格式化字符串 D3 直接传递给序列号的 .ToString() 方法调用;基于 -f 运算符 的替代方法将是:

    ('{0:D3}' -f $nr.Value++)
    
英文:

<!-- language-all: sh -->

Make the regex you pass to -replace match a run of digits (\d+) only if preceded by _Photo and succeeded by _, and replace those digits with the new sequence number:

$nr = @{ Value = 1 }
Get-ChildItem -File |
  Rename-Item -NewName { 
    $_.Name -replace &#39;(?&lt;=_Photo)\d+(?=_)&#39;, ($nr.Value++).ToString(&#39;D3&#39;) 
  } -WhatIf

<sup>Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf and re-execute once you're sure the operation will do what you want.</sup>

Note:

  • An aux. hashtable (@{ Value = 1 }) is used to contain the sequence number, which is necessary for technical reasons: delay-bind script blocks run in a child scope of the caller - see this answer for background information.

  • The -File switch passed to Get-ChildItem (one of whose built-in aliases on Windows is ls) limits processing to only files, not also directories.

  • The regex passed to -replace uses positive lookaround assertions ((?&lt;=...) and (?=...)), which ensure that patterns of interest precede and succeed the run of digits but without becoming part of what is captured.

  • The desired formatting string, D3 is passed to a .ToString() method call directly on the sequence number; the -f operator-based alternative would be:

    (&#39;{0:D3}&#39; -f $nr.Value++)
    

huangapple
  • 本文由 发表于 2023年6月29日 03:21:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定