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

huangapple go评论69阅读模式
英文:

PowerShell - Work with counter and renaming of files

问题

以下是已经翻译好的代码部分:

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

如果你需要任何进一步的帮助,请随时告诉我。

英文:

Please help with the following situation:

There are many photos need to be renamed according to the name of directory folder, where they are located + add index at the end of each new name in format PHOTO1000_NAMEA_1, PHOTO1001_NAMEA_2, PHOTO1002_NAMEB_1, PHOTO1003_NAMEB_2, PHOTO1004_NAMEC_1, PHOTO1005_NAMEC_2, etc.

Where:

a) PHOTO1000 (1001,1002) = counter of total quantity of renamed photos;
b) _1 (_2,_3) = indexing number of concrete new name of item.

In my version of code in part a) counter did not calculate items from "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 }

Please help with correct format of code.

Thanks!!

答案1

得分: 2

<!-- language-all: sh -->

使用两个[哈希表](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Hash_Tables),结合[延迟绑定脚本块](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_script_blocks#using-delay-bind-script-blocks-with-parameters),可以实现您的任务:

$totalCount = @{ value = 0 } # 总重命名文件的计数
$countPerDir = @{ } # 每个目录名称的重命名文件计数
Get-ChildItem -Recurse -Include *.jpg |
Rename-Item -NewName {
'PHOTO_{0}{1}{2}{3}' -f ++$totalCount.value,
$
.Directory.Name,
++$countPerDir[$.Directory.Name],
$
.Extension
} -WhatIf


<sup>注意:上面命令中的 [`-WhatIf` 通用参数](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_commonparameters#-whatif) 用于 _预览_ 操作。一旦确定操作会按您的期望执行,请删除 `-WhatIf` 并重新执行。</sup>

注意:

* 通过使用 [`Rename-Item`](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/rename-item),您实际上是在原地重命名文件,而不是在单一的目标目录中;如果需要后者,请改用 [`Move-Item`](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/move-item),并使用其 `-Destination` 参数。

* `$totalCount` 之所以是哈希表而不是简单的 `[int]` 变量,是因为延迟绑定脚本块在调用者的 _子_ 作用域中运行(与 `ForEach-Object` 和 `Where-Object` 脚本块不同),从子作用域引用哈希表使得能够跨作用域边界更新其条目。

* `$countPerDir` 哈希表跟踪每个目录名称中已重命名的文件数。`++$countPerDir[$_.Directory.Name]` 利用了两个行为:
  * 对尚不存在的条目进行赋值会隐式 *创建* 该条目(使用给定的键)。
  * 对刚刚创建的新条目应用 `++` 实际上将其视为 `0` 并返回 `1`。
英文:

<!-- language-all: sh -->

You can use two hashtables in combination with a delay-bind script block to implement your task:

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

<sup>Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf and re-execute once you're sure the operation will do what you want.</sup>

Note:

  • By using Rename-Item, you're actually renaming the files in place, not in a single, flat target directory; if you want the latter, use Move-Item with its -Destination parameter instead.

  • The only reason $totalCount is a hashtable rather than a simple [int] variable is that delay-bind script blocks run in a child scope of the caller (unlike ForEach-Object and Where-Object script blocks), and referencing a hashtable from the child scope enables updating its entries across scope boundaries.

  • The $countPerDir hashtable keeps track of how any files per directory name have been renamed. ++$countPerDir[$_.Directory.Name] takes advantage of two behaviors:

    • Assigning to an entry that didn't previously exists implicitly creates such an entry (with the given key).
    • Applying ++ to new entry that was just created effectively treats it like 0 and returns 1.

答案2

得分: 0

我根据您的问题理解提供了一个解决方案。

确保使用投票机制标记正确答案,如果对提供的内容满意。

# 设置包含要重命名的照片的目录路径
$dirPath = "C:\Temp\Photo"

$counter = 1000

# 获取指定路径中的所有目录
$dirs = Get-ChildItem -Path $dirPath -Directory -Recurse

# 循环遍历每个目录
foreach ($dir in $dirs) {
    # 获取当前目录中的所有文件
    $files = Get-ChildItem -Path $dir.FullName -File -Filter '*.jpg'

    # 初始化当前文件索引的计数器
    $index = 1

    # 遍历当前目录中的每个文件
    foreach ($file in $files) {
        # 构建新文件名
        # ("PHOTO_{0}_{1}{2}" -f $script:count, $_.Directory.Name, $_.Extension)
        if ($file.BaseName.StartsWith('PHOTO')) {
            Write-Warning ('文件 {0} 已经被重命名' -f $file.FullName)
            Continue
        }
        $newName = 'PHOTO{0}_{1}_{2}{3}' -f $counter, $file.BaseName, $index, $file.Extension

        # 重命名文件
        Rename-Item -Path $file.FullName -NewName $newName

        # 增加文件索引
        $index++
        $counter++
    }
}
英文:

I have provided a solution as I understood your question.
Make sure to use the voting mechanism to mark the correct answer if satisfied with what was provided.

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

$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 &#39;*.jpg&#39;

    # 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
        # (&quot;PHOTO_{0}_{1}{2}&quot; -f $script:count, $_.Directory.Name,$_.Extension)
        if ($file.BaseName.StartsWith(&#39;PHOTO&#39;)) {
            Write-Warning (&#39;File {0} has alread been renamed&#39; -f $file.FullName)
            Continue
        }
        $newName =&#39;PHOTO{0}_{1}_{2}{3}&#39; -f  $counter,$file.BaseName,$index, $file.Extension

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

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

答案3

得分: 0

我不看到你调用 $counter。你初始化它,但在 foreach 中没有再次调用它。

你有两个计数器 - 所有照片的总数,然后是基于 NAME_ 的索引,看起来是目录名称。

第一个计数器很简单 - 每次迭代后只需添加 $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)
        $counter++
        $index++
    }
}

看,我的结果

执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads220721_140129.jpg 目标:C:\Users\Doco\Downloads\PHOTO1000_Downloads_1.jpg”。
执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220720_211337_720.jpg 目标:C:\Users\Doco\Downloads\PHOTO1001_Downloads_2.jpg”。
执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220720_211337_773.jpg 目标:C:\Users\Doco\Downloads\PHOTO1002_Downloads_3.jpg”。
执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220721_203852_286.jpg 目标:C:\Users\Doco\Downloads\PHOTO1003_Downloads_4.jpg”。
执行操作“Rename File”目标“项目:C:\Users\Doco\OneDrive\Desktop\birthday invite.jpg 目标:C:\Users\Doco\OneDrive\Desktop\PHOTO1004_Desktop_1.jpg”。
执行操作“Rename File”目标“项目:C:\Users\Doco\OneDrive\Desktop\boop.jpg 目标:C:\Users\Doco\OneDrive\Desktop\PHOTO1005_Desktop_2.jpg”。

现在只需删除 -whatif。显然。

英文:

i don't see you calling $counter. You initiate it, but don't call it again in the foreach.

You have 2 counters going - total of all photos, and then index which is based off of NAME_ which looks like the directory name.

First counter is easy - just add $counter++ after each iteration. $index just needs to be based off of directory - probably simplest way to do this is group everything off of directory, and then $index++

behold - my answer

$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 (&quot;PHOTO{0}_{1}_{2}{3}&quot; -f 
        $counter, $item.Directory.Name,$index ,$item.Extension) - 
        WhatIf;$counter++;$index++}}

behold - my results

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

Now just remove -whatif. Obviously

答案4

得分: 0

这是我的版本,使用引用变量来计数:

[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
    }
}

请注意,代码部分不被翻译。

英文:

Here's my version, using reference variables for the counters:

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

huangapple
  • 本文由 发表于 2023年2月26日 21:47:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75572421.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定