PowerShell Remove-Item 不等待
PowerShell Remove-Item not waiting
如果有这段代码
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 以确保文件夹真正被删除?
或者我可能还想念其他东西?
如果您键入 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.
Because the Recurse parameter in Remove-Item has a known issue, the
command in this example uses Get-ChildItem to get the desired files,
and then uses the pipeline operator to pass them to Remove-Item .
按照规范的建议进行操作:
if(Test-Path -Path $OUT)
{
Get-ChildItem $OUT -Recurse | Remove-Item
}
New-Item -ItemType directory -Path $OUT
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
。
为了完整起见:您还可以使用安全快速的 .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
更新: 开始于(至少[1])Windows 10版本20H2
(不知道WindowsServerversion和build对应的那个;运行winver.exe
去查您的版本和构建),DeleteFile
Windows API 函数现在表现出 同步 行为,这 隐含地解决了 PowerShell 的问题Remove-Item
和 .NET 的 System.IO.File.Delete
/ System.IO.Directory.Delete
(但是,奇怪的是, 而不是 和 cmd.exe
的 rd /s
)。
Remove-Item -Recurse
竟然是异步,最终是因为WindowsAPI 文件和目录删除方法本质上是异步的 并且 Remove-Item
没有考虑到这一点。
这间歇性地、不可预测地以两种方式之一表现出来:
您的情况:删除后立即重新创建已删除的目录可能会失败,因为在尝试重新创建时删除可能尚未完成。
更典型的是:如果在尝试删除父目录时子目录或文件的删除尚未完成,则删除非空目录本身可能会失败 - 这在ServerFault answer marsze 链接到。
一个潜在的解决方法是通过清空来重用一个现有的目录——而不是删除并重新创建它。
但是,清空 Get-ChildItem $OUT -Recurse | Remove-Item -Recurse
的目录也容易出现间歇性故障,虽然可能不太常见。
该问题不仅影响 PowerShell 的 Remove-Item
,还影响 cmd.exe
的 rd /s
以及 .NET 的 [System.IO.Directory]::Delete()
:
截至 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1 / cmd.exe
10.0.17134.407 / .NET Framework 4.7.03056,.NET Core 2.1,Remove-Item
、rd /s
、[System.IO.Directory]::Delete()
都不可靠,因为它们无法解释 [=128] 的异步行为=] API file/directory-removal 函数:
对于提供可靠同步解决方法的自定义 PowerShell 函数,请参阅this answer。
[1] 我亲自验证了该问题已在版本 20H2
中解决,通过 运行 在 GitHub issue #27958 for hours without failure; suggests that the problem was resolved as early as version 1909
, starting with build 18363.657
, but Dinh Tran 中的测试发现问题在删除诸如 node_modules
之类的大型目录树时,从构建 18363.1316
开始, 未 得到解决。我找不到关于这个主题的任何官方信息。
如果有这段代码
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 以确保文件夹真正被删除? 或者我可能还想念其他东西?
如果您键入 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.
Because the Recurse parameter in Remove-Item has a known issue, the command in this example uses Get-ChildItem to get the desired files, and then uses the pipeline operator to pass them to Remove-Item .
按照规范的建议进行操作:
if(Test-Path -Path $OUT)
{
Get-ChildItem $OUT -Recurse | Remove-Item
}
New-Item -ItemType directory -Path $OUT
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
。
- 没有
为了完整起见:您还可以使用安全快速的 .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
更新: 开始于(至少[1])Windows 10版本20H2
(不知道WindowsServerversion和build对应的那个;运行winver.exe
去查您的版本和构建),DeleteFile
Windows API 函数现在表现出 同步 行为,这 隐含地解决了 PowerShell 的问题Remove-Item
和 .NET 的 System.IO.File.Delete
/ System.IO.Directory.Delete
(但是,奇怪的是, 而不是 和 cmd.exe
的 rd /s
)。
Remove-Item -Recurse
竟然是异步,最终是因为WindowsAPI 文件和目录删除方法本质上是异步的 并且 Remove-Item
没有考虑到这一点。
这间歇性地、不可预测地以两种方式之一表现出来:
您的情况:删除后立即重新创建已删除的目录可能会失败,因为在尝试重新创建时删除可能尚未完成。
更典型的是:如果在尝试删除父目录时子目录或文件的删除尚未完成,则删除非空目录本身可能会失败 - 这在ServerFault answer marsze 链接到。
一个潜在的解决方法是通过清空来重用一个现有的目录——而不是删除并重新创建它。
但是,清空 Get-ChildItem $OUT -Recurse | Remove-Item -Recurse
的目录也容易出现间歇性故障,虽然可能不太常见。
该问题不仅影响 PowerShell 的 Remove-Item
,还影响 cmd.exe
的 rd /s
以及 .NET 的 [System.IO.Directory]::Delete()
:
截至 Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.1 / cmd.exe
10.0.17134.407 / .NET Framework 4.7.03056,.NET Core 2.1,Remove-Item
、rd /s
、[System.IO.Directory]::Delete()
都不可靠,因为它们无法解释 [=128] 的异步行为=] API file/directory-removal 函数:
对于提供可靠同步解决方法的自定义 PowerShell 函数,请参阅this answer。
[1] 我亲自验证了该问题已在版本 20H2
中解决,通过 运行 在 GitHub issue #27958 for hours without failure; 1909
, starting with build 18363.657
, but Dinh Tran 中的测试发现问题在删除诸如 node_modules
之类的大型目录树时,从构建 18363.1316
开始, 未 得到解决。我找不到关于这个主题的任何官方信息。