【问题标题】:PowerShell Rename-Item SubStringPowerShell 重命名项子字符串
【发布时间】:2019-06-27 06:47:29
【问题描述】:

我有一个具有以下命名约定的文件目录:“### 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?我在这里错过了什么?

【问题讨论】:

  • 既然你知道前缀,我还是会这样做:$TestPath | Get-ChildItem - 文件 |重命名项目 -NewName { ($_.Name).Replace('#### ','') }
  • 对不起,我应该指定的,### 可以是任何 3 位数字。

标签: powershell


【解决方案1】:

您可以使用Remove,而不是使用SubString

Get-ChildItem -File | Rename-Item -NewName { $_.Name.Remove(0,4) }

【讨论】:

  • 奇怪的是,这与上面建议的在 name.substring 中省略第二个长度参数的结果相同。它截断了前 8 个字符而不是 4 个。
【解决方案2】:

如果您没有为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)

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


编辑

鉴于 OPs cmets,我进行了更多测试,而且确实……将结果从 Get-ChildItem 直接传送到 Rename-Item cmdlet 似乎存在问题。 (我使用的是 Powershell 5.1)

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

您可以像这样首先在变量中捕获文件集合:

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

或将Get-ChildItem 部分括在括号中,如PetSerAl 建议:

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

我在this answer找到了对此的解释:

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.

【讨论】:

  • 我也有同样的想法,但是当我省略第二个长度参数或使用 name.length -4 时,它会截断文件名的前 8 个字符。
  • 我真的看不出来..你能给我们举个真实的例子吗?
  • @user2234575 请参阅我的答案的编辑。我有一个可行的解决方案,但它也让我感到困惑..
  • 是的,我也发现了一些奇怪的行为,如果我重命名 27 个文件,它工作正常,第 28 个导致它失败。
  • @user2234575 在我的测试用例中,将 Foreach-Object 放入帮助中,所有文件都已正确重命名。它现在也对你有用吗?我必须说我以前从未遇到过这个错误,所以感谢学习经验! +1
【解决方案3】:

另一种解决方案,在每个位置检查#

Get-ChildItem -Path E:\temp\*#*  | Rename-Item -NewName  { $_.fullname.replace('#','') }

【讨论】:

  • 抱歉,我应该指定...# 是任何 0-9 字符的通配符。我只对删除前 4 个字符感兴趣,文件名的其余部分可能有数字和/或“#”。
猜你喜欢
  • 2011-12-27
  • 2021-08-02
  • 2013-12-18
  • 2017-05-26
  • 2017-07-02
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 2020-05-05
相关资源
最近更新 更多