Powershell 重命名多个文件夹(会出现错误!)
我是PowerShell新手,已经编写了以下脚本,使用ISE,尝试重命名同一目录中的一组文件夹,这些文件夹的日期格式严格为20201130到2020-11-30(只需添加破折号) 这个脚本还不错,但我有三个问题 1-当它运行时,抛出了一系列与Powershell 重命名多个文件夹(会出现错误!),powershell,Powershell,我是PowerShell新手,已经编写了以下脚本,使用ISE,尝试重命名同一目录中的一组文件夹,这些文件夹的日期格式严格为20201130到2020-11-30(只需添加破折号) 这个脚本还不错,但我有三个问题 1-当它运行时,抛出了一系列与重命名项相关的错误 错误: Rename-Item : Source and destination path must be different. At line:13 char:25 + ... ChildItem | Rename-Item -NewN
重命名项相关的错误
错误:
Rename-Item : Source and destination path must be different.
At line:13 char:25
+ ... ChildItem | Rename-Item -NewName { $_.Name -replace $file, $MyNewName ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (D:\Google Drive...Term 2\testings:String
) [Rename-Item], IOException
+ FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.Renam
eItemCommand
2-当我用一个名为(234567890)的文件夹测试它时,它仍然有效,尽管这个文件夹的长度不等于8
3-当发生上述重命名时,产生的名称是“1234-56-7890”,这很奇怪,因为$MyNewName
应该以2个字符结尾<代码>$file.Substring(6,2)
剧本:
$FileNameArr_All = (Get-ChildItem).Name
$i = 0
foreach($file in $FileNameArr_All){
if ( ($file -match "^\d+$") -and ($file.Length -eq 8) ){
[string] $MyNewName = $file.Substring( 0 , 4 )+"-"+$file.Substring( 4 , 2 )+"-"+$file.Substring( 6 , 2 )
#the actual renamining of the item, where the error is:
Get-ChildItem | Rename-Item -NewName { $_.Name -replace $file, $MyNewName }
$message = "the item " + $file + " has been renamed : " + $MyNewName
Write-Output $message
$i ++
Write-Output $file.Length
}
}
if ($i -eq 0){
Write-Output "No mathcing items found."
}
else{
$message2 = "total of items affected: " + $i
Write-Output $message2
}
我知道这是很多,但这是我的第一篇文章,也是我的第一个剧本,我非常感谢你对我的任何一点的帮助非常感谢:)而不是
Get-ChildItem | Rename-Item -NewName { $_.Name -replace $file, $MyNewName }
试试看
Rename-Item -Name $file -NewName $MyNewName
您可以让Where Object子句中的regex
-match
检查foldername是否正好有8位数字,并仅重命名以下数字:
$i = 0
Get-ChildItem -Path 'D:\Test' -Directory |
Where-Object { $_.Name -match '^\d{8}$' } |
ForEach-Object {
$newName = $_.Name -replace '(\d{4})(\d{2})(\d{2})', '$1-$2-$3'
Write-Host "Renaming folder $($_.FullName) to: $newName"
$_ | Rename-Item -NewName $newName -WhatIf
$i++
}
if ($i) {
Write-Host "Total of items affected: $i"
}
else {
Write-Host "No matching folder names found"
}
在这里,-WhatIf
开关确保您只看到将发生什么。实际上还没有任何东西被重命名。如果您对该输出感到满意,请从Rename Item cmdlet中删除-WhatIf
开关
此外,regex-replace
通过捕获3个不同的“backreference”中的数字并在它们之间用虚线输出,使得创建新名称格式比多次使用Substring()容易得多
如果您在任何时候都不关心写主机消息,那么代码可以缩短为
Get-ChildItem -Path 'D:\Test' -Directory |
Where-Object { $_.Name -match '^\d{8}$' } |
Rename-Item -NewName {$_.Name -replace '(\d{4})(\d{2})(\d{2})', '$1-$2-$3'} -WhatIf
该脚本的工作更加可靠,因为它使用“Get ChildItem”的retun对象,而不仅仅是文件/文件夹名
$i = 0
Get-ChildItem -Directory "C:\UserData\Test" | ForEach-Object {
if (($_.Name) -match "^\d{8}$") {
[System.String]$NewFolderName = ($_.Name).Insert(6, "-").Insert(4, "-")
Rename-Item -Path ($_.FullName) -NewName $NewFolderName
Write-Output ("the item {0} ({1}) has been renamed : {2}" -f ($_.Name), (($_.Name).Length), $NewFolderName)
$i++
}
}
if ($i) {
Write-Output ("total of items affected: {0}" -f $i)
} else{
Write-Output "No matching items found."
}
现有答案中有很多好的信息,但让我从概念上对其进行概括,并提供一个更精简的解决方案:
- 您正在逐个循环所有目录名,但由于只使用
-无参数-作为Get ChildItem
的输入,您试图重命名每个循环迭代中的所有项:rename Item
将所有文件和子目录发送到获取子项|重命名项…
;您实际上是在尝试将所有文件重命名为它们的现有名称(请参见下一个要点),这对于文件来说是一个安静的禁止操作,但是会触发重命名项
源路径和目标路径必须与您在目录中看到的
错误不同
是完整的新文件名,因此没有理由在原始目录名上使用$MyNewName
:因为-replace
不是现有名称的子字符串,$MyNewName
实际上是一个no-op-现有的$.name-replace$file,$MyNewName
被传递$.name
- 如果要重命名单个项目,只需传递
-而不是在($MyNewName
)中传递即可{…}
- 如果要重命名单个项目,只需传递
Get ChildItem
调用,该调用使用匹配感兴趣的目录,重命名项
,并使用延迟绑定脚本块插入-
字符。在通过基于正则表达式的匹配项的名称中:
上述操作将执行所需的重命名,并且由于使用,将打印以下内容(换行以确保可读性):
注:
- 如果要预览重命名操作,请使用with
重命名项
- 如果需要知道是否有任何文件匹配并因此重命名,请首先捕获变量中的
调用:Get ChildItem
$files = Get-ChildItem -Directory -Path ('[0-9]' * 8) $files | Rename-Item -NewName { $_.Name -replace '(.{4})(.{2})(.{2})', '$1-$2-$3' } -Verbose Write-Verbose -Verbose $(if ($files) { "$($files.Count) directories renamed." } else { 'No matching directories found.' })
VERBOSE: Performing the operation "Rename Directory" on target "Item: ...\12345678
Destination: ...\1234-56-78".
VERBOSE: Performing the operation "Rename Directory" on target "Item: ...\87654321
Destination: ...\8765-43-21".
$files = Get-ChildItem -Directory -Path ('[0-9]' * 8)
$files | Rename-Item -NewName { $_.Name -replace '(.{4})(.{2})(.{2})', '$1-$2-$3' } -Verbose
Write-Verbose -Verbose $(if ($files) { "$($files.Count) directories renamed." } else { 'No matching directories found.' })