$nr = 1
Get-ChildItem -Filter *.jpg | Rename-Item -Newname {
'{0}_{1:d3}.jpg' -f $_.Directory.Name, (Get-Variable nr).Value++
} -WhatIf
-WhatIf预览重命名操作;删除它,一旦您确信该命令将按预期执行。
- 一种更简洁、更高效(但更模糊)的替代方法是将
$nr 变量转换为[ref],以便您可以直接在调用者的范围内修改其值(通过.Value)。
$nr = 1
Get-ChildItem -Filter *.jpg | Rename-Item -Newname {
'{0}_{1:d3}.jpg' -f $_.Directory.Name, ([ref] $nr).Value++
} -WhatIf
以下部分解释了这些技术。
可选阅读:在延迟绑定脚本块或计算属性中修改调用者的变量:
您不能只在脚本块中使用$nr++ 来直接增加序列号的原因是:
以计算属性为例:
PS> $nr = 1; 1..2 | Select-Object { '#' + $nr++ }
'#' + $nr++
-------------
#1
#1 # !! the *caller's* $nr was NOT incremented
虽然您可以使用$global: 或$script: 等范围修饰符来显式引用父范围中的变量,但这些绝对范围引用可能无法按预期工作:要点:如果将代码移动到脚本中,$global:nr 不再引用使用$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
虽然这种技术很强大,但 cmdlet 调用会带来开销,而且有点冗长,但是:
使用 [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 没有被分配给,因此确实是调用者的 $nr 变量被引用。