我有一个具有以下命名约定的文件目录:'###一堆随机名称.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) } }
“名称长度”列为空
为什么子字符串不像$ _。Name.Length?我在这里想念什么?
答案 0 :(得分:1)
如果您没有为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)
可以工作,但是在这种情况下会显得过大。
考虑到OP的评论,我进行了更多测试,的确是……...将Get-ChildItem
的结果直接传递到Rename-Item
cmdlet似乎存在问题。 (我正在使用Powershell 5.1)
似乎您需要捕获来自Get-ChildItem
cmdlet的项目并迭代捕获的集合,以便重命名te文件。否则,某些文件可能会被处理和重命名多次。
您可以像这样首先捕获变量中的文件集合:
$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) }
我在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.
答案 1 :(得分:0)
可以使用SubString
来代替Remove
:
Get-ChildItem -File | Rename-Item -NewName { $_.Name.Remove(0,4) }
答案 2 :(得分:0)
另一种解决方案,该解决方案可以在所有地方检查#
Get-ChildItem -Path E:\temp\*#* | Rename-Item -NewName { $_.fullname.replace('#','') }