38

I'm trying to recursively delete all files and folders inside of a folder with Powershell via:

Remove-Item "C:\Users\user\Desktop\The_folder\*" -Recurse -Force

My problem is that whenever I run it, I get:

Cannot remove item C:\Users\user\Desktop\The_folder\Delete: The process cannot access the file 'C:\Users\user\Desktop\The_folder\Delete' because it is being used by another process.

How do I skip any files I don't have access to because they are in use (i.e. the same way a user would via GUI asking if wanting to skip all files that cannot be accessed)?

  • I tried the following, but received error:
    Remove-Item "C:\Users\mstjean\Desktop\The_folder\*" -Recurse -Force -ErrorAction Continue
    
      Remove-Item : Cannot remove item C:\Users\mstjean\Desktop\The_folder\Delete:
        The process cannot access the file 'C:\Users\mstjean\Desktop\The_folder\Delete'
        because it is being used by another process.
    
      At line:1 char:1
        + Remove-Item "C:\Users\mstjean\Desktop\The_folder\*" -Recurse -Force -ErrorAction ...
    
        + CategoryInfo: WriteError: (C:\Users\mstjea...e_folder\Delete:DirectoryInfo) [Remove-Item], IOException
        + FullyQualifiedErrorId:    RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
    
JW0914
  • 177
  • 1
  • 7
Phyziik
  • 515
  • 1
  • 5
  • 8
  • 4
    Does PowerShell stop when this happens? If that's the case, try adding `-ErrorAction Continue` to the `Remove-Item` command line. – Bill_Stewart Dec 14 '15 at 19:18
  • 1
    see http://stackoverflow.com/questions/8388650/powershell-how-can-i-stop-errors-from-being-displayed-in-a-script – djs Dec 14 '15 at 19:30
  • 1
    If the error is a terminating error, you will need to use `-ErrorAction SilentlyContinue` and then trap the using `try`/`catch`/`finally`. See `help about_Try_Catch_Finally` for details. – Bill_Stewart Dec 14 '15 at 19:50
  • 1
    -ErrorAction 'silentlycontinue' worked for my situation, no need to do a try/catch. – mhenry1384 Apr 11 '18 at 14:35

1 Answers1

67

If you want to suppress the error message and continue executing, you need to use -ErrorAction Ignore or -ErrorAction SilentlyContinue.

See Get-Help about_CommonParameters:

 -ErrorAction[:{Continue | Ignore | Inquire | SilentlyContinue | Stop |
     Suspend }]
     Alias: ea

     Determines how the cmdlet responds to a non-terminating error
     from the command. This parameter works only when the command generates
     a non-terminating error, such as those from the Write-Error cmdlet.

     The ErrorAction parameter overrides the value of the
     $ErrorActionPreference variable for the current command.
     Because the default value of the $ErrorActionPreference variable
     is Continue, error messages are displayed and execution continues
     unless you use the ErrorAction parameter.

     The ErrorAction parameter has no effect on terminating errors (such as
     missing data, parameters that are not valid, or insufficient
     permissions) that prevent a command from completing successfully.

     Valid values:

         Continue. Displays the error message and continues executing
         the command. "Continue" is the default value.

         Ignore.  Suppresses the error message and continues
         executing the command. Unlike SilentlyContinue, Ignore
         does not add the error message to the $Error automatic
         variable. The Ignore value is introduced in Windows
         PowerShell 3.0.

         Inquire. Displays the error message and prompts you for
         confirmation before continuing execution. This value is rarely
         used.

         SilentlyContinue. Suppresses the error message and continues
         executing the command.

         Stop. Displays the error message and stops executing the
         command.

         Suspend. This value is only available in Windows PowerShell workflows.
         When a workflow runs into terminating error, this action preference
         automatically suspends the job to allow for further investigation. After
         investigation, the workflow can be resumed.

If you're having terminating errors that -ErrorAction is not trapping, then you have to trap them yourself with a try / catch.

Here's a naive example:

Get-ChildItem "C:\Users\user\Desktop\The_folder\*" -Recurse -Force `
| Sort-Object -Property FullName -Descending `
| ForEach-Object {
    try {
        Remove-Item -Path $_.FullName -Force -ErrorAction Stop;
    }
    catch { }
}

Here, I'm using -ErrorAction Stop to turn all non-terminating errors into terminating errors. Try will trap any terminating error. The catch block is empty, however, so you're trapping everything and then not doing any error handling. The script will continue silently. This is basically equivalent to VBScript's On Error Resume Next. You have to iterate through the files, however, otherwise Remove-Item will stop at the first error.

Note that I have a Sort-Object in there. That's so the items coming through the pipeline are in reverse order. That way, files and subdirectories will be deleted before the directories that contain them. I'm not 100% sure if that method is perfect, but I think it should work. The alternative is really messy.

Obviously, there's no way to tell from output when an error occurs or what wasn't deleted. We're trapping all errors and then throwing them away. Usually an empty catch block is a really bad idea, so use this method with caution!

You'll note that I'm not actually testing to see if the file is opened or locked. That's because it's kind of a waste of time. We don't really care why the file can't be deleted, just that it can't and when it can't we skip it. It's easier (and faster) to try to delete the file and trap the failure than it is to check if it's locked, use a conditional to decide to delete the file, and then delete the file or continue.

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • It worked as expected, but the only thing, is that, in my case, I have a file that's open. This means that the error I was getting was to specify that the user is trying to delete an open file. Is there a way to skip any file that are open and delete the rest? I tried ErrorActon -Continue and it didn't work. – Phyziik Dec 15 '15 at 18:14
  • @Phyziik See my update for terminating errors. It's significantly more complex to deal with those, however. – Bacon Bits Dec 15 '15 at 20:00
  • It's worth noting that `-ErrorAction` does not appear to be supported on older versions of PowerShell on Windows 7. – DustWolf Aug 03 '20 at 11:41
  • @DustWolf That is not correct. `-ErrorAction` has always been a common parameter for Powershell commands. You can find articles from the designer of Powershell from November 2006, the month PS was released to v1.0, where he discusses the feature: https://devblogs.microsoft.com/powershell/erroraction-and-errorvariable/ – Bacon Bits Aug 03 '20 at 13:50
  • 1
    @BaconBits `-ErrorAction Ignore` then. Verified doesn't work, but works fine on Windows 10 – DustWolf Aug 03 '20 at 14:09
  • It's explained in the doc I quoted in my answer: "The Ignore value is introduced in Windows PowerShell 3.0." – Bacon Bits Aug 10 '22 at 15:27