2017-02-26 36 views
2

我有一堆在下面的模式命名的JPG图片文件不起作用:PowerShell中,重命名项如预期

0001-rand01_012.jpg 
0002-rand03_034.jpg 

我想通过去除前5个字符来获得的形式将其重命名:

rand01_012.jpg 

等。

我用下面的命令:

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 

我已经使用这个命令与成功的过去重命名这些文件。我得到这样随机结果的事实让我把头发拉出来。

+0

'(Get-ChildItem)| Rename-Item -NewName {$ _。Name.Substring(5)}' –

+0

对不起,为什么它会改变行为? – 4c74356b41

+0

@ 4c74356b41:在将该数组传递给'Rename-Item'之前,它首先显式地收集数组中的所有匹配文件。但是,虽然这使得_conceptual_ sense(首先枚举,以便重命名的文件不会干扰枚举),但我不认为这是必要的 - 请参阅我添加到我的答案中的脚注。 – mklement0

回答

4

TL;博士

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

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

您可以选择将(...)各地Get-ChildItem测序的清晰度,但是这不是绝对必要的。 [1]

这样:

  • 您排除不相关的文件前面。

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

    • 的东西去错了最可能的原因是导致相同文件名去掉5第一个字符经过1个多输入文件。

这听起来像您不慎运行此命令反复,所以你剪了5个字符。多次

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

一旦一个文件名有少于5个字符,你会得到的startIndex - 相关错误,因为[string]类的.Substring()方法没有。接受超出字符串长度的索引(尝试'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.jpg0002-rand01_012.jpg都将被重新命名为rand01_012.jpg,这失败一旦第一个已被重命名。

也就是说,让您的命令按照预期工作,所有文件名都是由于丢弃前5个字符而产生的。必须是唯一的。

下面是一个MCVE (Minimal, Complete, and Verifiable Example)

设置:

# 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 

在第三次运行的时候,所有的名字都太短了,你会得到的是Rename-Item : Cannot create a file when that file already exists.错误。


[1]围Get-ChildItem(...)确保匹配的文件被收集在一个阵列前面,被调用之前Rename-Item
这明确防止已重命名的文件被Get-ChildItem重新枚举,从而干扰迭代;然而,明确使用(...)在技术上没有必要,因为Get-ChildItemalways internally collects all files up front, across platforms的方式实现,因为它按名称对它们进行排序,这在名称被收集后本质上是唯一可能的。
在的光,无论你用(...)应不应该功能量相同,尽管调用没有(...)可能是更多的内存效率和速度稍快。