【发布时间】: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
我有一系列文件都命名为:
PRT14_WD_14220000_1.jpg
我需要在最后一个下划线之后和数字之前添加两个零,这样它看起来像 PRT14_WD_14220000_001.jpg
我试过了”
(dir) | rename-Item -new { $_.name -replace '*_*_*_','*_*_*_00' }
感谢任何帮助。
【问题讨论】:
标签: powershell filenames
与您尝试的最接近的是这个。在正则表达式中,通配符是.*。并且括号会分组以供稍后使用美元符号数字参考。
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
【讨论】:
以下假设您的.BaseName 的最后一部分将始终需要添加两个零。它是做什么的......
Get-Item/Get-ChildItem获得的fileinfo对象_作为分割目标将.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
【讨论】:
-replace operator 在 regexes (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。
(?<=_)[^_]+(?=\.) 匹配非_ 字符的非空运行 (+)。 ([^_]) 前面是 _ ((?<=_),后面是文字 . ((?=\.)),不包括前面的 _ 和后面的 . 来自 捕获的内容 匹配((?<=...) 和 (?=...) 是非捕获环顾断言)。
_ 之后和文件扩展名开始之前的字符。00$& 替换与 00 匹配的内容,然后是匹配捕获的内容 ($&)。
在后续评论中,您提到不仅要盲目插入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
【讨论】: