PowerShell -处理计数器和文件重命名

qnakjoqk  于 2023-03-18  发布在  Shell
关注(0)|答案(4)|浏览(150)

请在以下情况下提供帮助:
有许多照片需要根据目录文件夹的名称进行重命名,它们所在的位置+在每个新名称的末尾添加索引,格式为PHOTO1000_NAMEA_1,PHOTO1001_NAMEA_2,PHOTO1002_NAMEB_1,PHOTO1003_NAMEB_2,PHOTO1004_NAMEC_1,PHOTO1005_NAMEC_2等。
其中:
a)PHOTO 1000(1001,1002)=重命名照片总数计数器;B)_1(_2,_3)=项目具体新名称的索引号。
在我的a)部分代码版本中,计数器没有从“1000”,i++开始计算项目。

$count=1000
Get-ChildItem -Recurse -Include *.jpg | ForEach-Object -Process { Rename-Item -LiteralPath $_ -NewName ("PHOTO_{0}_{1}{2}" -f $script:count, $_.Directory.Name,$_.Extension) -WhatIf }

请帮助正确的代码格式。
谢谢!

7fhtutme

7fhtutme1#

您可以将两个hashtables与延迟绑定脚本块结合使用来实现您的任务:

$totalCount  = @{ value = 0 } # count of renamed files overall
$countPerDir = @{ } # count of renamed files per directory name
Get-ChildItem -Recurse -Include *.jpg | 
  Rename-Item -NewName {
    'PHOTO_{0}_{1}_{2}_{3}' -f ++$totalCount.value, 
                               $_.Directory.Name, 
                               ++$countPerDir[$_.Directory.Name], 
                               $_.Extension 
  } -WhatIf

注:上述命令中的-WhatIf公共参数 * 预览 * 操作。删除-WhatIf,并在确定操作将执行所需操作后重新执行。
注:

  • 通过使用Rename-Item,您实际上是在 * 原地 * 重命名文件,而不是在单个平面目标目录中重命名文件;如果您想要后者,请使用Move-Item及其-Destination参数。
  • $totalCount是一个哈希表而不是一个简单的[int]变量的唯一原因是延迟绑定脚本块在调用者的 child 作用域中运行(不像ForEach-ObjectWhere-Object脚本块),并且从子作用域引用哈希表允许跨越作用域边界更新其条目。
  • $countPerDir哈希表跟踪 * 每个目录名 * 的任何文件是如何重命名的。++$countPerDir[$_.Directory.Name]利用两种行为:
  • 对先前不存在的条目进行赋值会隐式地 * 创建 * 这样一个条目(使用给定的键)。
  • ++应用于刚创建的新条目,有效地将其视为0,并返回1
wljmcqd8

wljmcqd82#

我已经提供了一个解决方案,因为我理解你的问题。请确保使用投票机制,以标记正确的答案,如果满意所提供的。

# Set the path to the directory containing the photos to rename
$dirPath = "C:\Temp\Photo"

$counter = 1000

# Get all directories in the specified path
$dirs = Get-ChildItem -Path $dirPath -Directory -Recurse

# Loop through each directory
foreach ($dir in $dirs) {
    # Get all files in the current directory
    $files = Get-ChildItem -Path $dir.FullName -File -Filter '*.jpg'

    # Initialize a counter for the current file index
    $index = 1

    # Loop through each file in the current directory
    foreach ($file in $files) {
        # Build the new file name
        # ("PHOTO_{0}_{1}{2}" -f $script:count, $_.Directory.Name,$_.Extension)
        if ($file.BaseName.StartsWith('PHOTO')) {
            Write-Warning ('File {0} has alread been renamed' -f $file.FullName)
            Continue
        }
        $newName ='PHOTO{0}_{1}_{2}{3}' -f  $counter,$file.BaseName,$index, $file.Extension

        # Rename the file
        Rename-Item -Path $file.FullName -NewName $newName

        # Increment the file index
        $index++
        $counter++
    }
}
3gtaxfhh

3gtaxfhh3#

我没有看到你调用$counter。你启动了它,但是不要在前面再次调用它。
你有两个计数器-所有照片的总数,然后索引,这是基于名称,这看起来像目录名。
第一个计数器很简单--每次迭代后添加$counter即可。$index只需要基于目录--最简单的方法可能是将目录中的所有内容分组,然后添加$index
看-我的回答

$jpgs = Get-ChildItem -Recurse -Include *.jpg | group -Property Directory

$counter = 1000    
foreach ($group in $jpgs) {
    $index = 1
    foreach ($item in $group.Group) {
        rename-item -LiteralPath $item -NewName ("PHOTO{0}_{1}_{2}{3}" -f 
        $counter, $item.Directory.Name,$index ,$item.Extension) - 
        WhatIf;$counter++;$index++}}

看-我的结果

Performing the operation "Rename File" on target "Item: C:\Users\Doco\Downloads\20220721_140129.jpg Destination: C:\Users\Doco\Downloads\PHOTO1000_Downloads_1.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\Users\Doco\Downloads\IMG_20220720_211337_720.jpg Destination: C:\Users\Doco\Downloads\PHOTO1001_Downloads_2.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\Users\Doco\Downloads\IMG_20220720_211337_773.jpg Destination: C:\Users\Doco\Downloads\PHOTO1002_Downloads_3.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\Users\Doco\Downloads\IMG_20220721_203852_286.jpg Destination: C:\Users\Doco\Downloads\PHOTO1003_Downloads_4.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\Users\Doco\OneDrive\Desktop\birthday invite.jpg Destination: C:\Users\Doco\OneDrive\Desktop\PHOTO1004_Desktop_1.jpg".
What if: Performing the operation "Rename File" on target "Item: C:\Users\Doco\OneDrive\Desktop\boop.jpg Destination: C:\Users\Doco\OneDrive\Desktop\PHOTO1005_Desktop_2.jpg".

现在把-什么。显然

nlejzf6q

nlejzf6q4#

下面是我的版本,使用引用变量作为计数器:

[ref]$Total = 0
(Get-ChildItem -Directory -Recurse) | ForEach {
    $_ | Get-ChildItem *.jpg -File | ForEach -Begin {[ref]$subTotal = 0} -Process {
        $_ | Rename-Item -NewName {
            'Photo_{0:d4}_{1}_{2}{3}' -f $Total.Value++ , $_.Directory.Name , $subTotal.Value++ , $_.Extension
        } -WhatIf
    }
}

相关问题