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

Powershell重命名项,使用函数替换旧名称,powershell,rename-item-cmdlet,Powershell,Rename Item Cmdlet,我有一个文件列表: 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

我有一个文件列表:

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('$1', 10) + 12).ToString("00000")) + '$2')} -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\00001_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
并按摩数据。替换失败,因为字符串literal
$1
无法转换为整数。正如在类似问题中所讨论的:您可以使用scriptblock和.nNet regex静态方法
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
以拥有捕获组

替换不起作用的原因是因为-replace的工作方式。请参阅以下答案:。基本上,“$1”的字面意思是字符串“$1”,而正则表达式引擎并没有掌握它。