简体   繁体   English

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

[英]Powershell rename-item, replace old name using functions

I have a list of files:我有一个文件列表:

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>

I want to renamem those that start with five numbers and an underline.我想重命名以五个数字和一个下划线开头的那些。 The new name will add a number I specified to the leading numbers of those file names.新名称会将我指定的数字添加到这些文件名的前导数字中。 For example, if I add 10, the new names would be:例如,如果我添加 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>

Now my PowerShell code is:现在我的 PowerShell 代码是:

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

I can't find any errors in my code.我在我的代码中找不到任何错误。 But when I run it, I got the following error message:但是当我运行它时,我收到以下错误消息:

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

My question is, where I am wrong?我的问题是,我错在哪里? Is it because I should not use functions in the replacement part of the replace operator?是不是因为我不应该在replace操作符的替换部分使用函数? If so, how to write complex logic in -newname{} ?如果是这样,如何在-newname{}编写复杂的逻辑? Thanks.谢谢。

You cannot use -replace and massage the data at the time of the substitution.您不能在替换时使用-replace和按摩数据。 Your replacement was failing as the string literal $1 cannot be converted to integer.您的替换失败,因为字符串文字$1无法转换为整数。 As discussed in a similar question: Passing a function to Powershell's (replace) function you can use a scriptblock and the .nNet regex static method Replace .正如在类似问题中所讨论的: 将函数传递给 Powershell 的(替换)函数,您可以使用脚本块和 .nNet 正则表达式静态方法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

You can use the script block inline but getting it out makes for a little cleaner code.您可以使用内联脚本块,但将其取出会使代码更简洁一些。 However I would likely use -match and the returned $matches object to do the same thing.但是我可能会使用-match和返回的$matches对象来做同样的事情。

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

Note that I updated the where-object to have capture groups.请注意,我更新了where-object以具有捕获组。

Haha, I got an answer.哈哈,我有答案了。

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

Just found that I can use any code in the -newname{} block.刚刚发现我可以在-newname{}块中使用任何代码。 But I still don't understand why my -replace way did not work.但我仍然不明白为什么我的-replace方式不起作用。

I want to using function length and substring on "rename=item -newname" command, is it possible ?我想在“rename=item -newname”命令上使用函数长度和子字符串,这可能吗?
Thanks谢谢

(example) (例子)

  • current file name: 136(136)_210922_POsdfsdf_KKIM91473654_INVESSON CO.pdf当前文件名:136(136)_210922_POsdfsdf_KKIM91473654_INVESSON CO.pdf

  • new file name: 91473654.pdf新文件名:91473654.pdf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM