Powershell在文件扩展名和下划线之间删除文本

时间:2019-03-18 23:13:02

标签: powershell

我有一些混乱的PDF文件,其文件名中包含文本,需要删除。每个文件名的名称中都有多个下划线,具体取决于文件名的长度。我的目标是删除.pdf文件扩展名和最后一个_之间存在的文本。

例如,我有:

  • AB_NAME_NAME_NAME_NAME_DS_123_EN _6 .pdf
  • AC_NAME_NAME_NAME_DS_321_EN _10 .pdf
  • AD_NAME_NAME_DS_321_EN _101 .pdf

并希望将粗体部分删除:

  • AB_NAME_NAME_NAME_NAME_DS_123_EN.pdf
  • AC_NAME_NAME_NAME_DS_321_EN.pdf
  • AD_NAME_NAME_DS_321_EN.pdf

我是Powershell的新手,但是我进行了一些研究,发现Powershell - Rename filename by removing the last few characters这个问题很有帮助,但是并不能完全满足我的需求,因为我无法对要删除的字符的长度进行硬编码,因为它们的长度可能不同(2-4)

Get-ChildItem 'C:\Path\here' -filter *.pdf | rename-item -NewName {$_.name.substring(0,$_.BaseName.length-3) + $_.Extension}

似乎可以使用.splitregex来做到这一点,但我找不到解决方案。谢谢。

3 个答案:

答案 0 :(得分:2)

您可以使用srand类的LastIndexOf()方法来获取字符最后一个实例的索引。在您的情况下,应该这样做:

[string]

答案 1 :(得分:1)

-replace operatorregex结合使用可实现简洁的解决方案:

Get-ChildItem 'C:\Path\here' -Filter *.pdf | 
  Rename-Item -NewName { $_.Name -replace '_[^_]+(?=\.)' } -WhatIf

-WhatIf 预览重命名操作。删除它以执行实际的重命名。

  • _[^_]+匹配一个_字符,后跟一个或多个非{_字符([^-]

    • 如果只想(十进制)个数字\d)进行匹配,请改用_\d+
  • (?=\.)是与文字(?=...).)匹配的look-ahead assertion\.),即文件名扩展名的开头不包含在比赛中

  • 通过不为-replace提供替换操作数,它隐式地是空字符串来替换匹配的内容,从而有效地删除了最后一个_前缀文件名扩展名之前的令牌。


您还可以处理带有“双”扩展名的文件名,从而使正则表达式更强大;例如,上述解决方案将文件名a_bc.d_ef.pdf替换为a.c.pdf,即执行两次替换。为防止这种情况,请改用以下正则表达式:

$_.Name -replace '_[^_]+(?=\.[^.]+$)'

预见断言现在确保仅 last 扩展名匹配:文字.\.)后跟一个或多个(+)字符串<{<1> 末尾处的文字.[^.],否定的字符集([^...])以外的其他字符。 {1}}。

答案 2 :(得分:0)

只是为了展示另一种选择,

  • 要从Name中删除的部分是由BaseName拆分的_中的 last 元素
  • 这是[-1]拆分后的负索引
    Get-ChildItem 'C:\Path\here' -Filter *.pdf |%{$_.BaseName.split('_\d+')[-1]}
    6
    10
    101
  • 当拆分删除_时,必须再次应用删除它。

Get-ChildItem 'C:\Path\here' -Filter *.pdf | 
   Rename-Item -NewName { $_.Name -replace '_'+$_.BaseName.split('_')[-1] } -whatif

EDIT (修改后的变体),它在下划线处分割了BaseName
使用-split运算符和
而不删除分割字符 带有zero length lookahead

的RegEx
> Get-ChildItem 'C:\Path\here' -Filter *.pdf |%{($_.BaseName -split'(?=_\d+)')[-1]}
_6
_10
_101

Get-ChildItem 'C:\Path\here' -Filter *.pdf | 
    Rename-Item -NewName { $_.Name -replace ($_.BaseName -split'(?=_)')[-1] } -whatif