我有一些删除文件夹的代码,然后将文件从临时目录复制到该文件夹所在的位置。
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 黑客更快;但仍然不理想。 问题
更新
在单独的作业中运行删除(即使用下面的代码)并没有解决问题。
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/