Powershell 重命名项目,使用函数替换旧名称

Powershell rename-item, replace old name using functions

我有一个文件列表:

PS S:\temp> dir


    Directory: S:\temp


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         3/28/2016   2:07 AM          0 00001_asdfasdfsa df.txt
-a---         3/28/2016   2:07 AM          0 00002_asdfasdfsa df - Copy (3).txt
-a---         3/28/2016   2:07 AM          0 00003_asdfasdfsa df - Copy.txt
-a---         3/28/2016   2:07 AM          0 00004_asdfasdfsa df - Copy (6).txt
-a---         3/28/2016   2:07 AM          0 00005_asdfasdfsa df - Copy (5).txt
-a---         3/28/2016   2:07 AM          0 00006_asdfasdfsa df - Copy (4).txt
-a---         3/28/2016   2:07 AM          0 00007_asdfasdfsa df - Copy (2).txt
-a---         3/28/2016   2:07 AM          0 700006_asdfasdfsa df - Copy (4) - Copy.txt


PS S:\temp>

我想重命名以五个数字和一条下划线开头的那些。新名称会将我指定的数字添加到这些文件名的前导数字中。例如,如果我加 10,新名称将是:

PS S:\temp> dir


    Directory: S:\temp


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         3/28/2016   2:07 AM          0 00011_asdfasdfsa df.txt
-a---         3/28/2016   2:07 AM          0 00012_asdfasdfsa df - Copy (3).txt
-a---         3/28/2016   2:07 AM          0 00013_asdfasdfsa df - Copy.txt
-a---         3/28/2016   2:07 AM          0 00014_asdfasdfsa df - Copy (6).txt
-a---         3/28/2016   2:07 AM          0 00015_asdfasdfsa df - Copy (5).txt
-a---         3/28/2016   2:07 AM          0 00016_asdfasdfsa df - Copy (4).txt
-a---         3/28/2016   2:07 AM          0 00017_asdfasdfsa df - Copy (2).txt
-a---         3/28/2016   2:07 AM          0 700006_asdfasdfsa df - Copy (4) - Copy.txt


PS S:\temp>

现在我的 PowerShell 代码是:

dir * | ?{$_.name -match '^\d{5}_.+'} | Rename-Item -NewName {$_.name -replace '^(\d{5})(_.+)', ((([convert]::ToInt32('', 10) + 12).ToString("00000")) + '')} -whatif

我在我的代码中找不到任何错误。但是当我 运行 它时,我收到以下错误消息:

Rename-Item : The input to the script block for parameter 'NewName' failed. Exception calling "ToInt32" with "2" argument(s): "Could not find any recognizable digits."
At line:1 char:62
+ dir * | ?{$_.name -match '^\d{5}_.+'} | Rename-Item -NewName {$_.name -replace ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (S:\temp[=13=]001_asdfasdfsa df.txt:PSObject) [Rename-Item], ParameterBindingException
    + FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.RenameItemCommand

我的问题是,我哪里错了?是因为我不应该在 replace 运算符的替换部分使用函数吗?如果可以,那么复杂的逻辑如何写在-newname{}中呢?谢谢。

哈哈,我得到答案了

dir * | ?{$_.name -match '^\d{5}_.+'} | Rename-Item -NewName {(([convert]::toint32($_.name.substring(0, 5), 10) + 12).ToString("00000")) + $_.name.substring(5)} -whatif

刚刚发现我可以使用 -newname{} 块中的任何代码。但是我还是不明白为什么我的-replace方法没有用。

您不能使用 -replace 并在替换时修改数据。您的替换失败,因为字符串文字 </code> 无法转换为整数。正如在类似问题中所讨论的:<a href="">Passing a function to Powershell's (replace) function</a> 您可以使用脚本块和 .nNet 正则表达式静态方法 <code>Replace.

$replaceBlock = {
    # Groups 0 contains the whole match. 1 is the first group... and so on.
    ([convert]::ToInt32($args[0].Groups[1],10) + 12).ToString("00000") + $args[0].Groups[2]
}

Get-ChildItem | Where-Object{$_.name -match '^\d{5}_.+'} | Rename-Item -NewName {
    [Regex]::Replace($_.name, '^(\d{5})(_.+)', $replaceBlock)
} -whatif

您可以内联使用脚本块,但将其取出会使代码更简洁。但是我可能会使用 -match 和返回的 $matches 对象来做同样的事情。

Get-ChildItem | Where-Object{$_.name -match '^(\d{5})(_.+)'} | Rename-Item -NewName {
    ([int]$Matches[1] + 12).ToString("00000") + $Matches[2]
} -whatif

请注意,我更新了 where-object 以包含捕获组。