Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell - Skip files that cannot be accessed

Tags:

powershell

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 
like image 299
Phyziik Avatar asked Dec 14 '15 19:12

Phyziik


People also ask

How do I ignore an error in PowerShell?

If you need to suppress an error, you can use the ErrorAction switch to suppress an error for a single cmdlet or an ErrorAction preference variable to suppress errors globally.

What is SilentlyContinue in PowerShell?

-ErrorAction:SilentlyContinue suppresses the error message and continues executing the command. -ErrorAction:Stop displays the error message and stops executing the command. -ErrorAction:Suspend is only available for workflows which aren't supported in PowerShell 6 and beyond.


1 Answers

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.

like image 163
Bacon Bits Avatar answered Oct 05 '22 13:10

Bacon Bits