gpt4 book ai didi

powershell -++ 变量上的运算符未按 ScriptBlock 中的预期更改

转载 作者:行者123 更新时间:2023-12-03 09:52:20 26 4
gpt4 key购买 nike

我正在尝试通过在文件中添加基于递增计数器的前缀来重命名文件,例如:

$directory = 'C:\Temp'
[int] $count=71;

gci $directory | sort -Property LastWriteTime | `
rename-item -newname {"{0}_{1}" -f $count++, $_.Name} -whatif

然而,所有处理的文件都是 71_$count++ 中的 $count 从不递增且文件名前缀相同?为什么?


enter image description here

最佳答案

您不能在脚本 block 中直接使用 $count++ 来直接增加序列号的原因是:

  • Delay-bind script blocks - 例如您传递给 Rename-Item -NewName 的那个 - 和 calculated properties 中的脚本 block 在范围内运行

  • 因此,尝试修改调用者的变量反而会创建一个 block -在每次迭代中都超出范围的局部变量,以便下一次迭代再次从调用者的范围中看到原始值。

    • 要了解有关范围和隐式局部变量创建的更多信息,请参阅 this answer .

解决方法

一个实用但可能有限制的解决方法是使用范围说明符 $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

这会起作用:

  • 在交互式 session 中(在命令提示符下,在全局范围内)。

  • 在脚本中,只要 $count 变量在脚本的顶级作用域中被初始化。

    • 也就是说,如果您将代码移动到带有局部函数 $count 变量的函数,它将不再有效。

灵活的解决方案需要对父级范围的可靠相对引用:

有两种选择:

  • 概念清晰,但冗长且相对较慢,因为必须调用 cmdlet:(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任何 范围内初始化和递增一个global 变量,但给定即使在脚本执行结束后全局变量仍然存在,您还应该事先保存任何预先存在的 $global:count 值,然后再恢复它,这使得这种方法不切实际。

关于powershell -++ 变量上的运算符未按 ScriptBlock 中的预期更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56843044/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com