英文:
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 ((?<=...)
和(?=...)
),以确保感兴趣的模式位于数字运行之前和之后,但不包括在被捕获的内容中。- 有关正则表达式的解释和进行实验的选项,请参阅此 regex101.com 页面。
-
所需的格式化字符串
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 '(?<=_Photo)\d+(?=_)', ($nr.Value++).ToString('D3')
} -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 toGet-ChildItem
(one of whose built-in aliases on Windows isls
) limits processing to only files, not also directories. -
The regex passed to
-replace
uses positive lookaround assertions ((?<=...)
and(?=...)
), which ensure that patterns of interest precede and succeed the run of digits but without becoming part of what is captured.- For an explanation of the regex and the option to experiment with it, see this regex101.com page.
-
The desired formatting string,
D3
is passed to a.ToString()
method call directly on the sequence number; the-f
operator-based alternative would be:('{0:D3}' -f $nr.Value++)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论