Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 重命名多个文件夹(会出现错误!)_Powershell - Fatal编程技术网

Powershell 重命名多个文件夹(会出现错误!)

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

我是PowerShell新手,已经编写了以下脚本,使用ISE,尝试重命名同一目录中的一组文件夹,这些文件夹的日期格式严格为20201130到2020-11-30(只需添加破折号) 这个脚本还不错,但我有三个问题

1-当它运行时,抛出了一系列与
重命名项相关的错误
错误:

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
    不是现有名称的子字符串,
    $.name-replace$file,$MyNewName
    实际上是一个no-op-现有的
    $.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.' })
    

请允许我向新来者提供标准建议:如果你能给出答案,你将通过向未来读者展示解决问题的方法来帮助他们。要接受答案,请单击大标题✓ 答案左侧大数字下方的符号(您将获得2点声誉积分)。如果你至少有15个声望点,你也可以投票给其他有用的答案(也可以选择被接受的答案)。如果您的问题尚未解决,请提供反馈,或者,如果您自己找到了解决方案。
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.' })