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

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

PowerShell - Work with counter and renaming of files

问题

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

  1. $count=1000
  2. 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++.

  1. $count=1000
  2. 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

  1. <!-- language-all: sh -->
  2. 使用两个[哈希表](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

  1. <sup>注意:上面命令中的 [`-WhatIf` 通用参数](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_commonparameters#-whatif) 用于 _预览_ 操作。一旦确定操作会按您的期望执行,请删除 `-WhatIf` 并重新执行。</sup>
  2. 注意:
  3. * 通过使用 [`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` 参数。
  4. * `$totalCount` 之所以是哈希表而不是简单的 `[int]` 变量,是因为延迟绑定脚本块在调用者的 __ 作用域中运行(与 `ForEach-Object` `Where-Object` 脚本块不同),从子作用域引用哈希表使得能够跨作用域边界更新其条目。
  5. * `$countPerDir` 哈希表跟踪每个目录名称中已重命名的文件数。`++$countPerDir[$_.Directory.Name]` 利用了两个行为:
  6. * 对尚不存在的条目进行赋值会隐式 *创建* 该条目(使用给定的键)。
  7. * 对刚刚创建的新条目应用 `++` 实际上将其视为 `0` 并返回 `1`
英文:

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

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

  1. $totalCount = @{ value = 0 } # count of renamed files overall
  2. $countPerDir = @{ } # count of renamed files per directory name
  3. Get-ChildItem -Recurse -Include *.jpg |
  4. Rename-Item -NewName {
  5. &#39;PHOTO_{0}_{1}_{2}_{3}&#39; -f ++$totalCount.value,
  6. $_.Directory.Name,
  7. ++$countPerDir[$_.Directory.Name],
  8. $_.Extension
  9. } -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

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

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

  1. # 设置包含要重命名的照片的目录路径
  2. $dirPath = "C:\Temp\Photo"
  3. $counter = 1000
  4. # 获取指定路径中的所有目录
  5. $dirs = Get-ChildItem -Path $dirPath -Directory -Recurse
  6. # 循环遍历每个目录
  7. foreach ($dir in $dirs) {
  8. # 获取当前目录中的所有文件
  9. $files = Get-ChildItem -Path $dir.FullName -File -Filter '*.jpg'
  10. # 初始化当前文件索引的计数器
  11. $index = 1
  12. # 遍历当前目录中的每个文件
  13. foreach ($file in $files) {
  14. # 构建新文件名
  15. # ("PHOTO_{0}_{1}{2}" -f $script:count, $_.Directory.Name, $_.Extension)
  16. if ($file.BaseName.StartsWith('PHOTO')) {
  17. Write-Warning ('文件 {0} 已经被重命名' -f $file.FullName)
  18. Continue
  19. }
  20. $newName = 'PHOTO{0}_{1}_{2}{3}' -f $counter, $file.BaseName, $index, $file.Extension
  21. # 重命名文件
  22. Rename-Item -Path $file.FullName -NewName $newName
  23. # 增加文件索引
  24. $index++
  25. $counter++
  26. }
  27. }
英文:

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.

  1. # Set the path to the directory containing the photos to rename
  2. $dirPath = &quot;C:\Temp\Photo&quot;
  3. $counter = 1000
  4. # Get all directories in the specified path
  5. $dirs = Get-ChildItem -Path $dirPath -Directory -Recurse
  6. # Loop through each directory
  7. foreach ($dir in $dirs) {
  8. # Get all files in the current directory
  9. $files = Get-ChildItem -Path $dir.FullName -File -Filter &#39;*.jpg&#39;
  10. # Initialize a counter for the current file index
  11. $index = 1
  12. # Loop through each file in the current directory
  13. foreach ($file in $files) {
  14. # Build the new file name
  15. # (&quot;PHOTO_{0}_{1}{2}&quot; -f $script:count, $_.Directory.Name,$_.Extension)
  16. if ($file.BaseName.StartsWith(&#39;PHOTO&#39;)) {
  17. Write-Warning (&#39;File {0} has alread been renamed&#39; -f $file.FullName)
  18. Continue
  19. }
  20. $newName =&#39;PHOTO{0}_{1}_{2}{3}&#39; -f $counter,$file.BaseName,$index, $file.Extension
  21. # Rename the file
  22. Rename-Item -Path $file.FullName -NewName $newName
  23. # Increment the file index
  24. $index++
  25. $counter++
  26. }
  27. }

答案3

得分: 0

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

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

第一个计数器很简单 - 每次迭代后只需添加 $counter++。$index 只需基于目录 - 最简单的方法可能是根据目录分组,然后 $index++

看,我的答案

  1. $jpgs = Get-ChildItem -Recurse -Include *.jpg | group -Property Directory
  2. $counter = 1000
  3. foreach ($group in $jpgs) {
  4. $index = 1
  5. foreach ($item in $group.Group) {
  6. rename-item -LiteralPath $item -NewName ("PHOTO{0}_{1}_{2}{3}" -f $counter, $item.Directory.Name, $index, $item.Extension)
  7. $counter++
  8. $index++
  9. }
  10. }

看,我的结果

  1. 执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads220721_140129.jpg 目标:C:\Users\Doco\Downloads\PHOTO1000_Downloads_1.jpg”。
  2. 执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220720_211337_720.jpg 目标:C:\Users\Doco\Downloads\PHOTO1001_Downloads_2.jpg”。
  3. 执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220720_211337_773.jpg 目标:C:\Users\Doco\Downloads\PHOTO1002_Downloads_3.jpg”。
  4. 执行操作“Rename File”目标“项目:C:\Users\Doco\Downloads\IMG_20220721_203852_286.jpg 目标:C:\Users\Doco\Downloads\PHOTO1003_Downloads_4.jpg”。
  5. 执行操作“Rename File”目标“项目:C:\Users\Doco\OneDrive\Desktop\birthday invite.jpg 目标:C:\Users\Doco\OneDrive\Desktop\PHOTO1004_Desktop_1.jpg”。
  6. 执行操作“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

  1. $jpgs = Get-ChildItem -Recurse -Include *.jpg | group -Property Directory
  2. $counter = 1000
  3. foreach ($group in $jpgs) {
  4. $index = 1
  5. foreach ($item in $group.Group) {
  6. rename-item -LiteralPath $item -NewName (&quot;PHOTO{0}_{1}_{2}{3}&quot; -f
  7. $counter, $item.Directory.Name,$index ,$item.Extension) -
  8. WhatIf;$counter++;$index++}}

behold - my results

  1. 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;.
  2. 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;.
  3. 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;.
  4. 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;.
  5. 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;.
  6. 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

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

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

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

英文:

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

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

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:

确定