首页 > 解决方案 > PowerShell 重命名项子字符串

问题描述

我有一个具有以下命名约定的文件目录:'### Bunch of random names.txt',我想将文件重命名为相同的东西减去'###'。

应该足够简单:

Get-ChildItem -File | Rename-Item -newname { $_.Name.SubString(4,$_.Name.Length) }

但是我得到一个“索引和长度必须引用字符串中的位置。”

我通过以下方式验证 Name.Length:

Get-ChildItem -File | select Name, @{ N='name length';E={$_.Name.Length) } }

$_.Name.Length 为目录中的每个文件返回正确的 int 值

当我尝试这个时:

Get-ChildItem -File | select Name, @{N='name length';E={ $_.Name.SubString(4,$_.Name.Length) } }

“名称长度”列为空

为什么 substring 不像 $_.Name.Length?我在这里想念什么?

标签: powershell

解决方案


如果您没有为Substring()函数指定第二个(长度)参数,它将返回从第一个参数(字符索引)获取的字符串的其余部分,因此您可以简单地执行以下操作:

Get-ChildItem -File | ForEach-Object { $_ | Rename-Item -NewName $_.Name.SubString(4)}

你得到的错误"Index and length must refer to a location within the string."意味着第二个参数(想要的长度)超过了字符串的总长度,因为你正在切断前 4 个字符。

$_.Name.SubString(4,$_.Name.Length - 4)

会工作,但在这种情况下是矫枉过正的。


编辑

Get-ChildItem鉴于 OP 的评论,我测试了更多,而且确实......将结果从直接传输到Rename-Itemcmdlet似乎存在问题。(我使用的是 Powershell 5.1)

您似乎需要从cmdlet 中捕获Get-ChildItem项目并迭代捕获的集合以重命名文件。否则,可能会多次处理和重命名某些文件。

您可以先在变量中捕获文件集合,如下所示:

$files = Get-ChildItem -File
foreach($file in $files) { $file | Rename-Item -NewName $file.Name.SubString(4)}

或者按照PetSerAl的建议将Get-ChildItem部分括在括号中:

(Get-ChildItem -File) | Rename-Item -newname { $_.Name.SubString(4) }

我在这个答案中找到了一个解释:

There appears to be a bug that can cause bulk file renaming to fail under certain conditions. If the files are renamed by piping a directory listing to Rename-Item, any file that's renamed to something that's alphabetically higher than its current name is reprocessed by its new name as it's encountered later in the directory listing.


推荐阅读