使用Powershell根据包含父文件夹名称的公式自动批量重命名文件

时间:2018-11-20 12:26:01

标签: powershell batch-rename delay-bind

如何使用以下代码批量重命名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文件夹中。

3 个答案:

答案 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++的脚本块)和计算属性中的脚本块中运行范围

  • 因此,试图修改调用方的变量,而是创建了一个 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++}