如何使用以下代码批量重命名Powershell中的文件:
$nr=1;Get-ChildItem -Filter *.jpg |
Rename-Item -Newname {"PPPPPPP_{0:d3}.jpg" -f $global:nr++}
其中 PPPPPPP 是包含这些文件的父文件夹的名称。
预期输出:
PPPPPPP_001.jpg
PPPPPPP_002.jpg
PPPPPPP_003.jpg
文件位于C:\ USER \ MAIN \ BLABLABLA \ PPPPPPP文件夹中。
答案 0 :(得分:1)
通过脚本块内的$_.Directory.Name
获取父目录的名称。
将$nr
变量转换为[ref]
,以便您可以直接在调用者的作用域中(通过.Value
修改其值,这比使用作用域修饰符{{ 1}}-见下文。
$global:
$nr = 1
Get-ChildItem -Filter *.jpg | Rename-Item -Newname {
'{0}_{1:d3}.jpg' -f $_.Directory.Name, ([ref] $nr).Value++
} -WhatIf
预览重命名操作;一旦确信命令会按预期执行,请将其删除。
可选阅读:在延迟绑定脚本块或计算的属性中修改调用方的变量:
您不能仅在脚本块中使用-WhatIf
来直接增加序列号的原因是:
延迟绑定脚本块(例如传递给$nr++
的脚本块)和计算属性中的脚本块在中运行子范围。
Rename-Item -NewName
和Where-Object
的脚本块进行对比,这些脚本块直接在调用者的作用域中运行。因此,试图修改调用方的变量,而是创建了一个 block -局部变量,该变量在每次迭代中都超出范围,因此下一次迭代将再次出现看到原始值:
以计算所得的属性为例:
ForEach-Object
虽然您可以使用范围修饰符(例如PS> $nr = 1; 1..2 | Select-Object { '#' + $nr++ }
'#' + $nr++
-------------
#1
#1 # !! the *caller's* $nr was NOT incremented
或$global:
来显式引用父范围中的变量,但它们是绝对范围引用,可能无法用作预期的:一个恰当的例子:如果将代码移至脚本中,$script:
将不再引用由$global:nr
创建的变量。
快点:即使在脚本退出后,由于它们仍在当前会话中徘徊,因此通常应避免创建 global 变量。
可靠的方法是使用$nr = 1
调用可靠地引用直接父作用域:
Get-Variable -Scope 1
尽管此技术很强大,但它又麻烦又冗长。
但是您可以按以下方式提高效率:
PS> $nr = 1; 1..2 | Select-Object { '#' + (Get-Variable -Scope 1 nr).Value++ }
'#' + (Get-Variable -Scope 1 nr).Value++
------------------------------------------
#1
#2 # OK - $nr in the caller's scope was incremented
使用 $nr = 1; $nrVar = Get-Variable nr; 1..2 | Select-Object { '#' + $nrVar.Value++ }
类型提供了更简洁的选择,尽管该解决方案有点晦涩:
[ref]
将变量投射到PS> $nr = 1; 1..2 | Select-Object { '#' + ([ref] $nr).Value++ }
'#' + ([ref] $nr).Value++
---------------------------
#1
#2 # OK - $nr in the caller's scope was incremented
会返回一个对象,该对象的[ref]
属性可以访问并修改该变量的值。请注意,由于此时尚未.Value
被分配给,因此确实引用了调用者的 $nr
变量。
答案 1 :(得分:0)
编辑:由于mklement0的提示而被修改。
要获取父名称,请使用.Directory.Name
作为格式运算符的另一个参数
$nr=1
Get-ChildItem *.jpg -file|
Rename-Item -Newname {"{0}_{1:d3}.jpg" -f $_.Directory.Name,([ref]$nr).Value++} -whatIf
如果输出看起来不错,请删除-WhatIf
这仅在没有重叠范围进行重命名时才有效,在这种情况下,您应该使用临时扩展名。
在我的德语语言环境Windows上的示例输出
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\150.jpg Ziel: A:\test\test_007.jpg".
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\151.jpg Ziel: A:\test\test_008.jpg".
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\152.jpg Ziel: A:\test\test_009.jpg".
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\153.jpg Ziel: A:\test\test_010.jpg".
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\154.jpg Ziel: A:\test\test_011.jpg".
WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das Ziel "Element: A:\test\155.jpg Ziel: A:\test\test_012.jpg".
答案 2 :(得分:0)
另一种略有不同的方式:
$nr=1;Get-ChildItem -Filter *.jpg |
Rename-Item -Newname {"$(split-path -leaf $_.Directory)_{0:d3}.jpg" -f
$global:nr++}