file - 尽管文件夹已被删除,但移动项目会导致 "File Already Exists"错误

标签 file powershell directory windows-7-x64 powershell-5.0

我有一些删除文件夹的代码,然后将文件从临时目录复制到该文件夹​​所在的位置。

Remove-Item -Path '.\index.html' -Force
Remove-Item -Path '.\generated' -Force -Recurse  #folder containing generated files

#Start-Sleep -Seconds 10 #uncommenting this line fixes the issue

#$tempDir contains index.html and a sub folder, "generated", which contains additional files.  
#i.e. we're replacing the content we just deleted with new versions.
Get-ChildItem -Path $tempDir | %{
    Move-Item -Path $_.FullName -Destination $RelativePath -Force 
}

我收到一个间歇性错误,Move-Item : Cannot create a file when that file already exists.generated 的 Move-Item 行上小路。

我已经能够通过添加一个 hacky Start-Sleep -Seconds 10 来防止这种情况发生。第二个之后 Remove-Item陈述;虽然这不是一个很好的解决方案。

我认为问题是 Remove-Item 语句完成/代码移动到下一行,在操作系统 catch 实际文件删除之前;虽然这看起来很奇怪/令人担忧。注意:生成的文件夹中有大约 2,500 个文件(都在 1-100 KB 之间)。

没有其他进程访问这些文件夹(即我什至关闭了我的资源管理器窗口并测试了这个目录被排除在我的 AV 之外)。

我考虑过其他选择:
  • 使用 Copy-Item而不是 Move-Item .我不喜欢这个,因为它需要在不需要时创建新文件(即复制比移动慢)......它比我目前的 sleep 黑客更快;但仍然不理想。
  • 删除文件而不是文件夹,然后遍历子文件夹并将文件复制到新位置。这会起作用,但是对于一些应该很简单的事情,代码要多得多;所以我不想追求那个选项。
  • Robocopy 可以解决问题;但我更喜欢纯 PowerShell 解决方案。如果没有干净的解决方案,这是我最终会选择的选项。

  • 问题
  • 有没有人见过这个?
  • 这是一个错误,还是我错过了什么?
  • 有没有人知道修复/好的解决方法?


  • 更新

    在单独的作业中运行删除(即使用下面的代码)并没有解决问题。
    Start-Job -ScriptBlock {
        Remove-Item -Path '.\index.html' -Force
        Remove-Item -Path '.\generated' -Force -Recurse  #folder containing generated files
    } | Wait-Job | Out-Null
    
    #$tempDir contains index.html and a sub folder, "generated", which contains additional files.  
    #i.e. we're replacing the content we just deleted with new versions.
    Get-ChildItem -Path $tempDir | %{
        Move-Item -Path $_.FullName -Destination $RelativePath -Force 
    }
    

    更新 #2

    添加这个作品;即不是等待固定的时间,而是等待路径被删除/每秒检查一次。如果 30 秒后它没有被移除,我们假设它不会被移除;所以无论如何都要继续(这将导致 move-item 抛出一个错误,并在其他地方处理)。
    # ... remove-item code ...
    Start-Job -ScriptBlock {
        param($Path)
        while(Test-Path $Path){start-sleep -Seconds 1}
    } -ArgumentList '.\generated' | Wait-Job -Timeout 30 | Out-Null
    # ... move-item code ...
    

    最佳答案

    最后我选择了这个解决方案;不完美,但它有效。

    Remove-Item -Path '.\index.html' -Force
    Remove-Item -Path '.\generated' -Force -Recurse  #folder containing generated files
    
    #wait until the .\generated directory is full removed; or until ~30 seconds has elapsed
    1..30 | %{
        if (-not (Test-Path -Path '.\generated' -PathType Container)) {break;}
        Start-Sleep -Seconds 1
    }
    
    Get-ChildItem -Path $tempDir | %{
        Move-Item -Path $_.FullName -Destination $RelativePath -Force 
    }
    

    这与问题的更新 #2 中的工作相同;只是不需要工作的开销;只是循环直到文件被删除。

    以下是包装为可重用 cmdlet 的上述逻辑:
    function Wait-Item {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory, ValueFromPipeline, HelpMessage = 'The path of the item you wish to wait for')]
            [string]$Path
            ,
            [Parameter(HelpMessage = 'How many seconds to wait for the item before giving up')]
            [ValidateRange(1,[int]::MaxValue)]
            [int]$TimeoutSeconds = 30
            ,
            [Parameter(HelpMessage = 'By default the function waits for an item to appear.  Adding this switch causes us to wait for the item to be removed.')]
            [switch]$Remove
        )
        process {
            [bool]$timedOut = $true
            1..$TimeoutSeconds | %{
                if ((Test-Path -Path $Path) -ne ($Remove.IsPresent)){$timedOut=$false; return;}
                Start-Sleep -Seconds 1
            }
            if($timedOut) {
                Write-Error "Wait-Item timed out after $TimeoutSeconds waiting for item '$Path'"
            }
        }
    }
    
    #example usage:
    Wait-Item -Path '.\generated' -TimeoutSeconds 30 -Remove
    

    关于file - 尽管文件夹已被删除,但移动项目会导致 "File Already Exists"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43547874/

    相关文章:

    java - eclipse 说插入 "EnumBody"来完成 EnumDeclaration

    arrays - 用不同的数组值替换JSON中的符号

    powershell - 在 PowerShell 脚本中,如何还原包以解决错误 : This project references NuGet package(s) that are missing on this computer

    perl - 如何从一个文件中检索一组两行,引用另一个文件中的第一行?

    python - 如何将列中的整数替换为另一个文件、python 或 awk 中包含的另一个整数

    c++ - 如何在文件中存储每 channel 16 位的图像?

    powershell - 如何使用PowerShell从应用程序中过滤字符流?

    c++ - 如何布局C++代码: namespaces and similar file names in visual studio 2010

    azure - 有什么方法可以获取 CloudBlobDirectory 实例的创建日期吗?

    C#:如何打开选择了多个文件的 Windows 资源管理器窗口