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

标签 powershell scope pipe scriptblock rename-item-cmdlet

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

$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/

相关文章:

powershell - Cmd上的树看起来与Powershell上的树不同

powershell - 在PowerShell中阻止在线搜索获取帮助

powershell - 跨多个服务器的PowerShell文件比较

g++ - 在 g++ 中管道文件内容进行编译

java - 如何通过管道传输 JVM 堆转储

powershell - 是否可以在 PowerShell 中扩展索引器?

静态变量的 Java 范围以及在按钮操作监听器中使用变量

javascript - Nodejs EventEmitter - 定义监听器功能的范围

Java变量的作用域和生命周期

c - 检查另一个程序的输出的程序