I am trying to delete a directory recursively with rm -Force -Recurse somedirectory, I get several "The directory is not empty" errors. If I retry the same command, it succeeds.

Example:

PS I:\Documents and Settings\m\My Documents\prg\net> rm -Force -Recurse .\FileHelpers
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data\RunTime\_svn: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (_svn:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data\RunTime: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (RunTime:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests\Data: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (Data:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\FileHelpers.Tests: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (FileHelpers.Tests:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs\nunit\_svn: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (_svn:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs\nunit: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (nunit:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers\Libs: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (Libs:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Cannot remove item I:\Documents and Settings\m\My Documents\prg\net\FileHelpers: The directory is not empty.
At line:1 char:3
+ rm <<<<  -Force -Recurse .\FileHelpers
    + CategoryInfo          : WriteError: (I:\Documents an...net\FileHelpers:DirectoryInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
PS I:\Documents and Settings\m\My Documents\prg\net> rm -Force -Recurse .\FileHelpers
PS I:\Documents and Settings\m\My Documents\prg\net>

Of course, this doesn't happen always. Also, it doesn't happen only with _svn directories, and I don't have a TortoiseSVN cache or anything like that so nothing is blocking the directory.

Any ideas?

up vote 28 down vote accepted

help Remove-Item says:

The Recurse parameter in this cmdlet does not work properly.

and

Because the Recurse parameter in this cmdlet is faulty, the command uses the Get-Childitem cmdlet to get the desire d files, and it uses the pipeline operator to pass them to the Remove-Item cmdlet.

and proposes this alternative as an example:

get-childitem * -include *.csv -recurse | remove-item

So you should pipe get-childitem -recurse into remove-item.

  • Thanks. Just found this thread from 2006: vistax64.com/powershell/… looks like Microsoft is not really interested in fixing this. – Mauricio Scheffer Nov 9 '10 at 20:00
  • @mausch: See this more recent, but still unresolved, reference: Remove-Item -Recurse – Dennis Williamson Nov 9 '10 at 22:21
  • if you do a traversal and delete, you'll have to traverse the child directories first, and their files first. – fschwiet Dec 26 '10 at 22:26
  • 2
    At least the documentation says it doesn't work. – derekerdmann Nov 20 '11 at 4:12
  • 4
    I had to put both -force -recurse flags for Remove-Item, otherwise it kept me prompting "please confirm" Get-ChildItem -Path $Destination -Recurse | Remove-Item -force -recurse – Michael Freidgeim Jan 17 '12 at 6:37

@JamesCW: The problem still exists in PowerShell 4.0

I tried another workaround and it worked: use cmd.exe:

&cmd.exe /c rd /s /q $somedirectory
  • 1
    Good old rd /s /q! – JamesCW May 5 '16 at 18:24
  • I've tried every variation of Get-ChildItem; retry loops; calling iisreset before deleting and nothing seems to work reliably. I'm gonna try this one, even though when I first saw it I balked at having DOS inside my Powershell... – Peter McEvoy Aug 23 '16 at 8:04

The new version of PowerShell (PSVersion 4.0) has resolved this issue entirely and Remove-Item "targetdirectory" -Recurse -Force works without any timing problems.

You can check your version by running $PSVersiontable from within the ISE or PowerShell prompt. 4.0 is the version that ships with Windows 8.1 and Server 2012 R2, and it can be installed on previous versions of Windows as well.

  • 4
    Still occurs for me in PowerShell 4.0 – ajbeaven Nov 3 '15 at 19:39
  • 6
    Still occurs in PowerShell v5 !!!!!11!!1!1!!! – Richard Hauer Nov 25 '16 at 8:46
  • @RichardHauer well now I'm just confused – JamesCW Dec 4 '16 at 4:04
  • 2
    @JamesCW I've converted to the rd version. Aside from actually working, it's about 3x faster – Richard Hauer Dec 4 '16 at 4:28

The current answer won't actually delete a directory, just its children. Furthermore it will have problems with nested directories as it will again be trying to delete a directory before its contents. I wrote something to delete the files in the correct order, would still have the same problem though sometimes the directory would still be around afterward.

So, now I use something that will catch the exception, wait, and retry (3 times):

For now I'm using this:

function EmptyDirectory($directory = $(throw "Required parameter missing")) {

    if ((test-path $directory) -and -not (gi $directory | ? { $_.PSIsContainer })) {
        throw ("EmptyDirectory called on non-directory.");
    }

    $finished = $false;
    $attemptsLeft = 3;

    do {
        if (test-path $directory) {
            rm $directory -recurse -force
        }

        try {
            $null = mkdir $directory
            $finished = $true
        } 
        catch [System.IO.IOException] {
            Start-Sleep -Milliseconds 500
        }

        $attemptsLeft = $attemptsLeft - 1;
    } 
    while (-not $finished -and $attemptsLeft -gt 0)

    if (-not $finished) {
        throw ("Unable to clean and recreate directory " + $directory)
    }
}
  • This is good but I still had problems with it. If the mkdir command runs before the system completes the rm command it can throw a System.UnauthorizedAccessException with a FullyQualifiedErrorId of ItemExistsUnauthorizedAccessError. I.e., the directory hasn't been deleted by the OS yet (on my slow HDD). So that error needs to be caught too. And it's a non-terminating error, so the ErrorAction needs to be set to Stop. I also put the rm command in the try block too, just in cases there are transient IO errors when deleting. – Mark Lapierre May 26 '16 at 14:02
  • I can't believe this even has to be done. Damn, Powershell sucks! – jcollum Jul 12 '17 at 16:20

To delete the directory and its contents takes two steps. First delete the contents, then the folder itself. Using the workaround for the faulty recursive remove item the solution would look like this:

Get-ChildItem -Path "$folder\\*" -Recurse | Remove-Item -Force -Recurse
Remove-Item $folder

This way you can remove the parent directory as well.

  • 1
    This is exactly what the accepted answer said. Do you have anything to add? – Michael Hampton Dec 14 '13 at 0:11
  • 1
    They are pointing out that the accepted answer does not delete the directory itself, hence it takes two steps. – Paul George May 2 '14 at 15:01
  • 1
    The Remove-Item command your piping into has the same problem that originally stated. It might stumble on a directory item that is non-empty in the same way. – Dejan Feb 26 '16 at 12:16
  • @Dejan This directory could not still be empty if the first line of this code worked, could it? – Ifedi Okonkwo Jun 7 '16 at 14:22

This is what I have working:

$Target = "c:\folder_to_delete"

Get-ChildItem -Path $Target -Recurse -force |
  Where-Object { -not ($_.psiscontainer) } |
   Remove-Item –Force

Remove-Item -Recurse -Force $Target

This first line deletes all files in the tree. The second deletes all the folders including the top.

Take ownership of the files / directories first using Takeown.exe then delete

https://learn-powershell.net/2014/06/24/changing-ownership-of-file-or-folder-using-powershell/

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.