Powershell,重命名项目没有按预期工作
Powershell, rename-item doesn't work as expected
我有一堆按以下模式命名的 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\temp223-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
等等
我过去曾使用此命令成功重命名此类文件。我得到如此随机的结果这一事实让我抓狂。
tl;dr
确保只处理感兴趣的文件:
(Get-ChildItem -File [0-9][0-9][0-9][0-9]-*.jpg) |
Rename-Item -NewName {$_.name.Substring(5)} -WhatIf
上面命令中的-WhatIf
common parameter预览操作。一旦您确定该操作将执行您想要的操作,请删除 -WhatIf
。
在 PowerShell [Core] 6+ 中,将 (...)
放置在 Get-ChildItem
周围不再是 技术上 所必需的,而是可取的。[ 1]
这样:
您预先排除了不相关的文件。
即使出现问题,您也可以更正问题并再次运行命令以仅重新处理失败的文件,而不会影响之前重命名的文件。
- 出现问题的最可能原因是超过 1 个输入文件导致在删除第 5 个字符后 相同 文件名。
听起来你错误地 运行 命令 重复 ,所以你截掉了 5 个字符。 多次:
0001-rand01_01.jpg
-> rand01_01.jpg
-> _01.jpg
一旦文件名少于 5 个字符,您将得到与 startIndex
相关的错误,因为 [string]
class 的 .Substring()
方法不接受超出字符串长度的索引(尝试 'ab'.Substring(3)
)。
也就是说,由于您 运行宁 Get-ChildItem
没有过滤器,因此 return all (非隐藏)子项,您可能正在处理 不相关的文件或什至是名称太短的目录。
Cannot create a file when that file already exists.
错误只是由通常 return 有效地 return 空字符串 return 新名称的脚本块导致的后续错误,因此 Rename-Item
有点含糊地抱怨您不能将文件重命名为当前名称。
也就是说,在 第一个 运行 期间,您甚至可能会遇到 Cannot create a file when that file already exists
错误,即如果有超过 1 个输入文件它的前 5 个字符。截断结果相同的文件名。
例如,0001-rand01_012.jpg
和 0002-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
确保匹配的文件收集在 array, 预先,在Rename-Item
被调用之前。
这明确地防止了已经重命名的文件被 Get-ChildItem
重新枚举,从而干扰迭代。 (...)
的显式使用 在技术上 在 PowerShell [Core] 6+ 中不再需要(它 在 中是 所必需的Windows PowerShell (5.1-)),因为 Get-ChildItem
是以 always internally collects info about all files up front, across platforms 的方式 实现的 ,因为它将它们排序名称,这本质上只有在收集完所有名称后才有可能。
鉴于此,无论你是否使用(...)
,功能上应该是一样的,尽管使用(...)
是可取的,因为它不依赖于什么相当于 实现细节 (documentation 没有提到输出是如何排序的)。
我有一堆按以下模式命名的 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\temp223-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
等等
我过去曾使用此命令成功重命名此类文件。我得到如此随机的结果这一事实让我抓狂。
tl;dr
确保只处理感兴趣的文件:
(Get-ChildItem -File [0-9][0-9][0-9][0-9]-*.jpg) |
Rename-Item -NewName {$_.name.Substring(5)} -WhatIf
上面命令中的-WhatIf
common parameter预览操作。一旦您确定该操作将执行您想要的操作,请删除 -WhatIf
。
在 PowerShell [Core] 6+ 中,将 (...)
放置在 Get-ChildItem
周围不再是 技术上 所必需的,而是可取的。[ 1]
这样:
您预先排除了不相关的文件。
即使出现问题,您也可以更正问题并再次运行命令以仅重新处理失败的文件,而不会影响之前重命名的文件。
- 出现问题的最可能原因是超过 1 个输入文件导致在删除第 5 个字符后 相同 文件名。
听起来你错误地 运行 命令 重复 ,所以你截掉了 5 个字符。 多次:
0001-rand01_01.jpg
-> rand01_01.jpg
-> _01.jpg
一旦文件名少于 5 个字符,您将得到与 startIndex
相关的错误,因为 [string]
class 的 .Substring()
方法不接受超出字符串长度的索引(尝试 'ab'.Substring(3)
)。
也就是说,由于您 运行宁 Get-ChildItem
没有过滤器,因此 return all (非隐藏)子项,您可能正在处理 不相关的文件或什至是名称太短的目录。
Cannot create a file when that file already exists.
错误只是由通常 return 有效地 return 空字符串 return 新名称的脚本块导致的后续错误,因此 Rename-Item
有点含糊地抱怨您不能将文件重命名为当前名称。
也就是说,在 第一个 运行 期间,您甚至可能会遇到 Cannot create a file when that file already exists
错误,即如果有超过 1 个输入文件它的前 5 个字符。截断结果相同的文件名。
例如,0001-rand01_012.jpg
和 0002-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
确保匹配的文件收集在 array, 预先,在Rename-Item
被调用之前。
这明确地防止了已经重命名的文件被 Get-ChildItem
重新枚举,从而干扰迭代。 (...)
的显式使用 在技术上 在 PowerShell [Core] 6+ 中不再需要(它 在 中是 所必需的Windows PowerShell (5.1-)),因为 Get-ChildItem
是以 always internally collects info about all files up front, across platforms 的方式 实现的 ,因为它将它们排序名称,这本质上只有在收集完所有名称后才有可能。
鉴于此,无论你是否使用(...)
,功能上应该是一样的,尽管使用(...)
是可取的,因为它不依赖于什么相当于 实现细节 (documentation 没有提到输出是如何排序的)。