如果有这段代码
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以确保文件夹已真正删除? 还是我想念其他东西?
答案 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