使用 Powershell 反转一组文件名中的序列号

Using Powershell to reverse the sequence numbers in a set of file names

我刚开始使用 PowerShell(以及相关的编码),我想做的就是重命名我的文件。

我有 222 个名为

的 .jpg
"REF_10001.jpg" 
"REF_10002.jpg" 
"REF_10003.jpg" 
etc

但我的问题是它们的顺序错误,我需要反转它们,例如我需要

"REF_10001.jpg" --> "REF_10222.jpg"

反之亦然。

"REF_10222.jpg" --> "REF_10001.jpg"

有办法吗?为了正确重命名我的文件,我花了好几个小时才意识到它们的顺序是错误的,我很想在这一点上单独做它们。

此外,如果有人可以帮助我更改文件以阅读

"REF.0001.jpg" 
"REF.0002.jpg" 
etc. 

那就太好了。

或者如果我的要求不可行,在我开始尝试重命名它们之前,我有一个图像序列的备份文件夹,文件读取

_0221_Layer 1.jpg
_0220_Layer 2.jpg
...
_0000_Layer 222.jpg

我需要更改它们以便

"_0221_Layer 1.jpg"    -->  "Ref.0001.jpg"
...
"_0000_Layer 222.jpg"  -->  "Ref.0222.jpg"

试试这个:

Get-ChildItem ".\Pics\*.jpg" | 
    ForEach-Object {$i = 1} {
            Rename-Item  -LiteralPath $_.FullName -NewName "$($_.BaseName)-$i.jpg"
            $i++
    }

Get-ChildItem ".\Pics\*.jpg" | 
    ForEach-Object {$j = 222} {
        Rename-Item  -LiteralPath $_.FullName -NewName "REF_$("1{0:0000}" -f $j).jpg"
        $j--
    }

这对我来说似乎有点低效,因为你需要枚举两次,但它适用于我的测试文件,所以希望足以解决你眼前的问题。

第一个循环将唯一的 'tag' 添加到文件名中,该文件名后来被丢弃 - 这是必需的,否则最终会发生冲突(例如,如果您尝试将 "REF_10001" 命名为 "REF_10222",它将失败,因为后者已经存在。

以下适用于可变数量的文件,并且还执行所需的名称转换(除了反转序列号之外):

# Enumerate the files in reverse alphabetical order - which thanks to the 0-padding
# is equivalent to the reverse sequence-number order - and rename them with 
# an ascending 0-padded sequence number.
# Note that in-place renaming is only possible because the new filename pattern
# - REF.*.jpg - doesn't conflict with the old one, REF_1*.jpg
$iref = [ref] 0  # sequence-number helper variable
Get-ChildItem -Filter REF_1*.jpg | Sort-Object Name -Descending |
  Rename-Item -NewName { 'REF.{0:0000}.jpg' -f (++$iref.Value) } -WhatIf

注意:使用 -WhatIf 预览 命令实际上没有 运行 它。 如果预览显示预期的操作,请删除 -WhatIf 以实际执行它。

注意需要使用 [ref] 类型的辅助。序列号的变量,并通过计算新名称的脚本块 ({ ... }) 中的 .Value 属性 递增它,因为脚本块在不同的变量范围内运行,因此不能直接修改调用者范围内的变量。

我的假设:

  • 我们无法预先知道文件名中的数字是否总是相互跟随
  • 我们事先不知道这些数字的位数
  • 我只接受以 REF_ 开头、后跟数字并以扩展名 jpg 结尾的文件

所以我提出了一个解决方案,将名字与最后一个反转,第二个与最后一个反转,依此类推:

$DirWithFiles="C:\Temp\DirWithFilesToRename"

#Creation to new dir for copy
$Temporatydir=  [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory $Temporatydir

#get all file jgp with format REF_ + Number + .jpg and order by number
$ListFile=Get-ChildItem $DirWithFiles -File -Filter "REF_*.jpg" | where BaseName -Match "^REF_\d{1,}$" | select Fullname, Name, @{N="Number";E={[int]($_.BaseName -split '_')[1]}} | sort Number

#copy files into new temporary dir and rename 1 position by N position, 2 by N-1, 3 by N - 2 etc...
for ($i = 0; $i -lt ($ListFile.Count / 2 ); $i++)
{ 
    Copy-Item $ListFile[$i].FullName "$Temporatydir$($ListFile[$ListFile.Count-$i - 1].Name)" -Force
    Copy-Item $ListFile[$ListFile.Count-$i - 1].FullName "$Temporatydir$($ListFile[$i].Name)" -Force
}

#Copy all files in temporary dir to initial dir with overwriting
Get-ChildItem $Temporatydir | Copy-Item -Destination $DirWithFiles


#delete temporary dir
Remove-Item $Temporatydir -Recurse

一个简单的颠倒顺序的方法是:

  • 每个文件号减去最高的数字+1
  • 删除与 -1 相乘的结果负号或使用 [math]::abs() 函数。
  • 要从 (Base)Name 获取数字,正则表达式 '^REF_1(\d+)?' 捕获 () 没有前导 1 的数字。
  • 格式字符串运算符"REF.{0:0000}.jpg" -f用于创建插入计算出的新数字的名称,其中包含 4 个位置
  • 随着前缀的变化,存在从另一端覆盖文件的危险。

Get-ChildItem REF_1*.jpg | 
  Where-Object BaseName -match '^REF_1(\d+)?' |
    Rename-Item -NewName {"REF.{0:0000}.jpg" -f (-1 *($Matches[1]-223))} -whatif

如果输出看起来正常,请删除尾随 -WhatIf 参数。

示例输出最后一行:

What if: Performing the operation "Rename File" on target "Item: REF_10222.jpg
Destination: REF.0001.jpg".