Powershell - Skip files that cannot be accessed

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.

Tags:

Powershell