If have this piece of code
if(Test-Path -Path $OUT)
{
Remove-Item $OUT -Recurse
}
New-Item -ItemType directory -Path $OUT
Sometimes it works, but sometimes the New-Item line produces a PermissionDenied ItemExistsUnauthorizedAccessError error. Which, I assume, means that the previous Remove-Item was not completely performed yet and the folder cannot be created because it still exists.
If I insert a sleep there
if(Test-Path -Path $OUT)
{
Remove-Item $OUT -Recurse
Start-Sleep -s 1
}
New-Item -ItemType directory -Path $OUT
then it works always. How can I force Remove-Item to ensure that the folder is really removed? Or maybe I miss something else?
Remove-Item 1 Description. The Remove-Item cmdlet deletes one or more items. ... 2 Examples. This example deletes all of the files that have names that include a dot (.) from the C:\Test folder. 3 Parameters. Prompts you for confirmation before running the cmdlet. ...
Here are the following parameters of PowerShell Remove-Item mention below: Confirm: It is possible that by mistake we can run delete command and we know a delete command can do very blunder, so for such type of situation Confirm will be very useful as it will ask you once before deleting.
This command deletes a file that is both hidden and read-only. PowerShell. Remove-Item -Path C:Testhidden-RO-file.txt -Force. It uses the Path parameter to specify the file. It uses the Force parameter to delete it. Without Force, you cannot delete read-only or hidden files.
Filter: Here we can specify filter parameters for Remove-item command. Force: Many times when the file is open we could not be able to delete it, so by using the command -Force we can delete it. Here it will give access to remove those items which are not allowed to remove, for example, if there is any file with read-only access ...
Update: Starting with (at least [1]) Windows 10 version 20H2
(I don't know that Windows Server version and build that corresponds to; run winver.exe
to check your version and build), the DeleteFile
Windows API function now exhibits synchronous behavior, which implicitly solves the problems with PowerShell's Remove-Item
and .NET's System.IO.File.Delete
/ System.IO.Directory.Delete
(but, curiously, not with cmd.exe
's rd /s
).
Remove-Item -Recurse
is unexpectedly asynchronous, ultimately because the Windows API methods for file and directory removal are inherently asynchronous and Remove-Item
doesn't account for that.
This intermittently, unpredictably manifests in one of two ways:
Your case: recreating a removed directory immediately after removal can fail, because the removal may not have completed yet by the time re-creation is attempted.
More typically: Removing a nonempty directory itself can fail, if removal of a subdirectory or file hasn't completed yet by the time an attempt is made to remove the parent directory - this is demonstrated in the ServerFault answer marsze links to.
A potential workaround is to reuse an existing directory by emptying it - instead of deleting and recreating it.
However, emptying the directory with Get-ChildItem $OUT -Recurse | Remove-Item -Recurse
is also susceptible to intermittent failures, though likely less often.
The problem not only affects PowerShell's Remove-Item
, but also cmd.exe
's rd /s
as well as .NET's [System.IO.Directory]::Delete()
:
As of 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, neither Remove-Item
, nor rd /s
, nor [System.IO.Directory]::Delete()
work reliably, because they fail to account for the asynchronous behavior of the Windows API file/directory-removal functions:
cmd.exe
bug reportFor a custom PowerShell function that provides a reliably synchronous workaround, see this answer.
[1] I've personally verified that the issue is resolved in version 20H2
, by running the tests in GitHub issue #27958 for hours without failure; this answer suggests that the problem was resolved as early as version 1909
, starting with build 18363.657
, but Dinh Tran finds that the issue is not resolved as of build 18363.1316
when removing large directory trees such as node_modules
. I couldn't find any official information on the subject.
For completeness' sake: You can also use the safe and fast .NET methods:
if ([System.IO.Directory]::Exists($OUT)) {
[System.IO.Directory]::Delete($OUT, $true)
}
[System.IO.Directory]::CreateDirectory($OUT)
Note:
Depending on where you get the value of $OUT
you might want to convert it to a full path first to make sure the .NET methods remove the correct directory (see @mklement0`s comment):
$fullPath = Convert-Path $OUT
If you type Get-Help Remove-Item -Detailed
you'll see:
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 .
Do what specification recommends:
if(Test-Path -Path $OUT)
{
Get-ChildItem $OUT -Recurse | Remove-Item
}
New-Item -ItemType directory -Path $OUT
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With