我试图通过在文件中添加基于递增计数器的前缀来重命名文件,例如:
rosa = resource_path("rosa.png")
然而,所有处理过的文件都是$directory = 'C:\Temp'
[int] $count=71;
gci $directory | sort -Property LastWriteTime | `
rename-item -newname {"{0}_{1}" -f $count++, $_.Name} -whatif
中的71_
和$count
永不递增,并且文件名是否前缀相同?为什么?
答案 0 :(得分:5)
不能仅在脚本块中使用$count++
来直接增加序列号的原因是:
Delay-bind script blocks-例如您传递给Rename-Item -NewName
的脚本-calculated properties中的脚本块在 child 范围内运行< / strong>。
Where-Object
和ForEach-Object
的脚本块进行对比,这些脚本块直接在调用者的作用域中运行。因此,试图修改调用方的变量,而是创建了一个 block -局部变量,该变量在每次迭代中都超出范围,因此下一次迭代将再次出现从调用者的作用域中看到原始值。
一种实用但可能有限制的解决方法是使用范围说明符$script:
-即$script:count
-引用调用者的$count
变量:>
$directory = 'C:\Temp'
[int] $count=71
gci $directory | sort -Property LastWriteTime |
rename-item -newname { '{0}_{1}' -f $script:count++, $_.Name } -whatif
这将起作用:
在交互式会话中(在命令提示符下,在全局范围内)。
在脚本中,只要在脚本的顶级范围内初始化了$count
变量。
$count
变量的 function 中,它将不再起作用。灵活的解决方案需要可靠的 relative 引用 parent 范围:
有两种选择:
(Get-Variable -Scope 1 count).Value++
gci $directory | sort -Property LastWriteTime |
rename-item -newname { '{0}_{1}' -f (Get-Variable -Scope 1 count).Value++, $_.Name } -whatif
([ref] $count).Value++
gci $directory | sort -Property LastWriteTime |
rename-item -newname { '{0}_{1}' -f ([ref] $count).Value++, $_.Name } -whatif
[ref] $count
实际上与Get-Variable -Scope 1 count
相同(假设在父作用域中设置了$count
变量)
注意:理论上,您可以使用$global:count
来初始化和递增 any 范围内的 global 变量,但是考虑到全局变量甚至在脚本执行结束后,您还应该预先保存任何预先存在的$global:count
值,然后再恢复它,这使该方法不切实际。
答案 1 :(得分:1)
@ mklement0的答案是正确的,但是我认为这比处理引用更容易理解:
Get-ChildItem $directory |
Sort-Object -Property LastWriteTime |
ForEach-Object {
$NewName = "{0}_{1}" -f $count++, $_.Name
Rename-Item $_ -NewName $NewName -WhatIf
}
答案 2 :(得分:1)
哇,最近有很多事情发生。这是我当前最喜欢的foreach多脚本块替代方案。带有通配符的gci稍后提供了$ _的完整路径。您不需要在管道或运算符之后使用反引号连续字符。
$directory = 'c:\temp'
gci $directory\* | sort LastWriteTime |
foreach { $count = 71 } { rename-item $_ -newname ("{0}_{1}" -f
$count++, $_.Name) -whatif } { 'done' }