我一直在使用Powershell来简化创建目录,重命名和移动文件中的重复性任务。我正在处理视频和PDF文件,其中文件名所需的语法非常明确。到目前为止,我已经能够纠正遇到的所有常见错误,但是这个错误让我很困惑。
我文件的正确语法包括:
01A-50_02A-50-CIPP-PRE.MP4
01AA-50_02AA-50-CIPP-PNSL.PDF
W01AA-48_02AA-48-CIPP-PST-CMP.MPG
我收到了大量看起来像这样的文件:
01A-50-02A-50-CIPP-PRE.MP4
01AA-50-02AA-50-CIPP-PNSL.PDF
W01AA-48-02AA-48-CIPP-PST-CMP.MPG
我需要用下划线替换第二个破折号,同时保持其他破折号不受影响。我可以在excel的帮助下批量进行此操作,但我希望有一个短代码可以找到并更正此语法错误,而不必将列表导出到excel,使用文本到列,然后连接字母数字部分一起回到。我也不想手动更正所有这些文件名。
根据我的研究,不可能定位要替换的特定字符。我最想想的是,我找到了一个涉及REGEX的解决方案,并确定并替换了模式。我对此无能为力。
我将使用此代码的方式是:打开包含未命名文件的文件夹,在其中打开Powershell窗口,从桌面上的txt文件复制代码,然后将其粘贴到Powershell中。
对此将提供任何帮助。
答案 0 :(得分:4)
使用-replace
运算符和正则表达式:
Get-ChildItem |
Rename-Item -NewName { $_.Name -replace '^([^_-]+-[^_-]+)-', '$1_' } -WhatIf
-WhatIf
预览重命名操作;删除它以执行实际的重命名。
正则表达式'^([^_-]+-[^_-]+)-'
在文件名的开头(-
)处捕获前两个^
分隔的令牌,并使用捕获组((...)
)进行捕获除第二个-
之外的令牌。
[^_-]+
捕获既不是-
也不是_
的所有非空字符。还排除了_
,以防止误以为正确的文件名。对于那些,不排除_
会匹配第一个 3 令牌,并在其中插入其他 _
。替换操作数$1_
使用第一个(也是唯一的)捕获组($1
)的值后跟文字_
来替换正则表达式匹配的内容,即有效地将第二个-
替换为_
。
如果给定文件名与正则表达式不匹配(如果它已经正确),则该名称按原样返回,这在Rename-Item
上下文中是一个安静的no-op。
答案 1 :(得分:1)
查看您的示例,似乎第二个-
总是出现在数字之间。像$Variable -replace 'REGEX','_'
使用以下正则表达式将与之匹配。
(?<=[0-9])(.)(?=[0-9])
()
创建一个要匹配的组,它是一个捕获组。
?<=
是正向查找,它与主表达式之前的组匹配,但不包含在结果中
[0-9]
是字符集,匹配0到9之间的任何字符。
.
匹配除换行符之外的任何字符
?=
是一个正向预测,它与主表达式后的一组匹配,而不包含在结果中
我建议使用Regexr测试和学习正则表达式。
答案 2 :(得分:1)
该RegEx:(?<=(^|\n)[^-]*-[^-]*)-
怎么样?
或作为完整命令(使用对Replace Part of File Name Powershell的回答):
Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=^[^-_]+-[^-_]+)-','_'}
答案 3 :(得分:1)
您可以在前两个-
处拆分字符串,然后通过-
和_
将它们连接起来:
$name = '01A-50-02A-50-CIPP-PRE.MP4'
$first,$second,$rest = $name -split '-',3
$newName = "${first}-${second}_${rest}"
答案 4 :(得分:1)
谢谢所罗门·乌科! 那几乎就是我想要的。
Get-ChildItem |重命名项-NewName {$ .name -replace'(?<=(^ | \ n)[^-] *-[^-] *)-',''}
在我可以抛出的所有示例中,它都工作得很好,除了... 如果我在一组混在一起的错误命名和正确命名的文件上运行代码,则会在不属于该文件的地方添加另一个下划线...
"E21U-50A_E21U_50-CIPP-PST-CMP"
代替
"E21U-50A_E21U-50-CIPP-PST-CMP"
解决这个问题很容易。
我要做的就是首先将所有_
替换为-
。
Get-ChildItem | Rename-Item -NewName {$_.name -replace '_','-'}
Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=(^|\n)[^-]*-[^-]*)-','_'}
感谢所有有其他想法的人。诚然,我没有尝试过它们,因为此解决方案是我尝试过的第一个解决方案,它确实成功了。
但是,在完成工作后,我将尝试其他解决方案。
再次感谢。