Powershell,重命名项目没有按预期工作

时间:2017-02-26 16:03:53

标签: powershell rename-item-cmdlet

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

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

我已经使用此命令重命名过去的这些文件并成功。我得到如此随机的结果这一事实让我脱掉了头发。

1 个答案:

答案 0 :(得分: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 - &gt; rand01_01.jpg - &gt; _01.jpg

一旦文件名少于5个字符,您就会收到与startIndex相关的错误,因为[string].Substring()方法没有#&# 39; t接受超出字符串长度的索引(尝试'ab'.Substring(3))。

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

Cannot create a file when that file already exists.错误只是脚本块产生的后续错误,通常会返回有效返回空字符串的新名称,所以Rename-Item有点模糊地抱怨你可以&#39; t将文件重命名为其当前名称。

也就是说,在第一次运行期间,您甚至可能会遇到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

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

[1]在Get-ChildItem中包含(...)可确保匹配的文件在数组预先中收集,之前调用Rename-Item 这明确阻止了已重命名的文件被Get-ChildItem重新枚举,从而干扰了迭代;明确使用(...) 技术上不是必需的,因为Get-ChildItem是以always internally collects all files up front, across platforms的方式实现,因为它按顺序对它们进行排序名称,只有在收集了所有名称后才有可能 鉴于此,尽管使用(...)是可取的,但是否使用(...) 功能是否相同,因为它不依赖于实现详情。 功能