PowerShell Remove-Item不等待

时间:2018-11-08 12:22:47

标签: powershell filesystems synchronous ntfs

如果有这段代码

if(Test-Path -Path $OUT) 
{ 
    Remove-Item $OUT -Recurse 
}
New-Item -ItemType directory -Path $OUT

有时可以,但是有时New-Item行会产生 PermissionDenied ItemExistsUnauthorizedAccessError 错误。我认为这意味着以前的Remove-Item尚未完全执行,并且无法创建该文件夹,因为该文件夹仍然存在。

如果我在那儿睡觉

if(Test-Path -Path $OUT) 
{ 
    Remove-Item $OUT -Recurse 
    Start-Sleep -s 1
}
New-Item -ItemType directory -Path $OUT

然后它总是可以工作。 如何强制Remove-Item以确保文件夹已真正删除? 还是我想念其他东西?

4 个答案:

答案 0 :(得分:4)

Remove-Item -Recurse意外地是异步 ,最终是因为用于删除文件和目录的Windows API方法本质上是异步的和{{ 1}}不能解决这个问题。

这种间歇性的,不可预测的表现为以下两种方式之一:

  • 您的情况:在删除之后立即重新创建已删除目录可能会失败,因为在尝试重新创建时可能尚未完成删除。

  • 更常见的情况是:如果在尝试删除父目录之前尚未完成子目录或文件的删除,则删除非空目录本身可能会失败-这在{{3 }}链接到的链接。

ServerFault answer提供了一种解决方法:代替重新创建目录,只需将其清空并重新使用它即可,从而绕过了问题

但是,具有Remove-Item的目录 清空 也容易受到间歇性故障的影响,尽管可能性较小。

>

该问题不仅影响PowerShell的Get-ChildItem $OUT -Recurse | Remove-Item -Recurse,还影响Remove-Item的{​​{1}}以及.NET的cmd.exe

从Windows PowerShell v5.1开始/ PowerShell Core 6.2.0-preview.1 / rd /s 10.0.17134.407 / .NET Framework 4.7.03056,.NET Core 2.1,都不是{{1} },[System.IO.Directory]::Delete()cmd.exe也不能可靠地工作,因为它们无法解决Windows API文件/目录删除功能的异步行为:< / p>

有关提供可靠的同步解决方法自定义PowerShell功能,请参见.NET Core bug report

答案 1 :(得分:3)

Remove-Item命令有一个known issue

尝试以下方法:

if (Test-Path $OUT) 
{ 
    # if exists: empty contents and reuse the directory itself
    Get-ChildItem $OUT -Recurse | Remove-Item -Recurse
}
else
{
    # else: create
    New-Item -ItemType Directory -Path $OUT
}

注意:

  • Get-ChildItem命令仅查找非隐藏文件和子目录,因此清空目标目录可能不完整;要也包含隐藏项,请添加-Force

  • 类似地,将-Force添加到-RemoveItem,以强制删除设置了只读属性的文件。

    • 没有-Force的情况下,清空可能仍会不完全,但是在这种情况下,您会遇到非终止错误;如果要将它们视为终止错误,也请添加-ErrorAction Stop

答案 2 :(得分:3)

出于完整性考虑:您还可以使用安全快速的.NET方法:

if ([System.IO.Directory]::Exists($OUT)) {
    [System.IO.Directory]::Delete($OUT, $true)
}
[System.IO.Directory]::CreateDirectory($OUT)

注意:

根据获取$OUT值的位置,可能需要先将其转换为完整路径,以确保.NET方法删除正确的目录(请参阅@ mklement0的注释):

$fullPath = Convert-Path $OUT

答案 3 :(得分:2)

如果您输入Get-Help Remove-Item -Detailed,则会看到:

Example 4: Delete files in subfolders recursively
PS C:\>Get-ChildItem * -Include *.csv -Recurse | Remove-Item

This command deletes all of the CSV files in the current folder and all subfolder recursively.
     

由于Remove-Item中的Recurse参数存在一个已知问题,因此   在此示例中,命令使用Get-ChildItem获取所需的文件,   然后使用管道运算符将它们传递给Remove-Item。

执行规范建议的内容:

if(Test-Path -Path $OUT) 
{ 
    Get-ChildItem $OUT -Recurse | Remove-Item
}
New-Item -ItemType directory -Path $OUT
相关问题