使用 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".
我刚开始使用 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".