4

我有一堆按以下模式命名的 jpg 图像文件:

0001-rand01_012.jpg
0002-rand03_034.jpg

我想通过删除前 5 个字符来重命名它们以获取表单:

rand01_012.jpg

ETC..

我使用以下命令:

Get-ChildItem | Rename-Item -NewName {$_.name.Substring(5)}

将其与 -whatif 标志一起使用时,我收到预期的消息:

Performing the operation "Rename File" on target "Item: C:\Users\xxxx\Documents\xx xx\temp2\0123-rand16_030.jpg Destination: C:\Users\
xxxx\Documents\xx xx\temp2\rand16_030.jpg".

但是删除whatif会给我这种类型的错误:

Rename-Item : The input to the script block for parameter 'NewName' failed. Exception calling "Substring" with "1" argument(s): "startIndex cannot be 
larger than length of string.

其次是一大堆:

Rename-Item : Cannot create a file when that file already exists.

文件本身被重命名,删除了随机数量的字符,而不是预期的 5 个。所以他们最终变成了:

01.jpg
01.jpg
.
.
.
d14_001.jpg

等等

我过去曾使用此命令成功重命名此类文件。我得到如此随机的结果的事实让我把头发拔了出来。

4

1 回答 1

8

tl;博士

确保只处理感兴趣的文件:

(Get-ChildItem -File [0-9][0-9][0-9][0-9]-*.jpg) |
  Rename-Item -NewName {$_.name.Substring(5)} -WhatIf

上面命令中的-WhatIfcommon 参数预览操作。-WhatIf 一旦您确定该操作将执行您想要的操作,请删除。
PowerShell [Core] 6+中,放置(...)技术上Get-ChildItem不再是必要的,但建议使用。 [1]

那样:

  • 您预先排除不相关的文件。

  • 即使出现问题,您也可以更正问题并再次运行命令以仅重新处理失败的文件,而不会影响先前重命名的文件。

    • 出现问题的最可能原因是超过 1 个输入文件在删除 5 个第一个字符后导致相同的文件名。

听起来你错误地重复运行命令,所以你已经切断了 5 个字符。多次

0001-rand01_01.jpg-> rand01_01.jpg->_01.jpg

一旦文件名少于 5 个字符,您将收到startIndex-related 错误,因为[string]该类的.Substring()方法不接受超出字符串长度的索引 (try 'ab'.Substring(3))。

也就是说,由于您在Get-ChildItem没有过滤器的情况下运行并因此返回所有(非隐藏)子项,您可能正在处理不相关的文件,甚至是名称太短的目录。

这些Cannot create a file when that file already exists.错误只是由脚本块导致的后续错误,该脚本块通常返回新名称,有效地返回空字符串,因此Rename-Item有点模糊地抱怨您无法将文件重命名为其当前名称。

也就是说,您甚至可以在第一次Cannot create a file when that file already exists运行期间遇到错误,即如果超过 1 个输入文件的前 5 个字符。砍掉的结果是相同的文件名。

例如,0001-rand01_012.jpgand0002-rand01_012.jpg都将被重命名为rand01_012.jpg,一旦第一个被重命名就会失败。

也就是说,为了让您的命令按预期工作,删除前 5 个字符产生的所有文件名。必须是唯一的。

这是一个MCVE(最小、完整和可验证的示例)

设置:

# Create and change to temp dir.
Set-Location (mkdir temp)
# Create sample input files named 0001-rand01_01.jpg, 0002-rand01_02.jpg, ...
# Note how the suffixes after the first 5 char. must be *unique*.
1..9 | %{ $null > "000${_}-rand01_0${_}.jpg" }

第一次运行:

# No errors
> (Get-ChildItem -File) | Rename-Item  -NewName { $_.Name.Substring(5) }
# Show new names
> Get-ChildItem | Select Name

Name         
----         
rand01_01.jpg
rand01_02.jpg
rand01_03.jpg
rand01_04.jpg
rand01_05.jpg
rand01_06.jpg
rand01_07.jpg
rand01_08.jpg
rand01_09.jpg

第二次运行产生:

Name    
----    
1_01.jpg
1_02.jpg
1_03.jpg
1_04.jpg
1_05.jpg
1_06.jpg
1_07.jpg
1_08.jpg
1_09.jpg

在第 3 次运行时,所有名称都太短,您将得到的只是Rename-Item : Cannot create a file when that file already exists.错误。


[1] 封闭确保匹配的文件被收集在一个Get-ChildItem数组在前面,在被调用之前。 这明确地防止已经重命名的文件被重新枚举并因此干扰迭代。在 PowerShell [Core] 6+ Windows PowerShell ( 5.1- )中必需的)技术上不再需要显式使用(...)Rename-Item
Get-ChildItem(...)Get-ChildItem,因为它按名称对它们进行排序,这本质上只有在收集了所有名称之后才有可能。
鉴于此,尽管使用是可取的,但无论您是否使用,在功能(...)上都应该相同,因为它不依赖于实现细节文档没有提到输出的排序方式)。 (...)

于 2017-02-26T16:18:05.453 回答