user973223
user973223

Reputation: 179

Catch `Get-ChildItem` errors on a file-by-file basis

I'm using Get-ChildItem -Recurse to search a directory. I can't guarantee that everything Get-ChildItem will hit will be accessible. I want to log these failures, but not fail the entire Get-ChildItem -Recurse command. Right now I have

Get-ChildItem -Recurse $targetdir -ErrorAction Inquire `
        | where { $_.Name -eq $name } `
        | foreach {
            echo-indented "Found $(hash $_) at $($_.FullName)"
            $_
        }

The code in question is the -ErrorAction Inquire. If I did -ErrorAction Stop, I would have to put a try-catch somewhere. It would have to be around the entire pipeline, right? In that case, childitems that would have been found after the inaccessible one will not be found and written out. So what else can I do?

Upvotes: 2

Views: 2976

Answers (2)

js2010
js2010

Reputation: 27516

You can use the -ErrorVariable common parameter to save the errors to a variable.

Get-ChildItem -recurse foo -ErrorVariable err
$err

Upvotes: 1

HAL9256
HAL9256

Reputation: 13483

For Get-ChildItem -Recurse, specifying the -ErrorAction won't really help you here. It will only cause access deny errors to either be:

  • Terminating (-ErrorAction Stop) where everything just stops. (not what you want)
  • Non-terminating (the default -ErrorAction Continue) which is what you want, as it will continue.

As for logs, with the default -ErrorAction Continue, all access denies are logged to the $Error variable. We can then parse through the exception records to get the information that we need:

#Start by clearing the error variable 
$Error.Clear()

#Execute Get-ChildItem with -ErrorAction Continue

ls -Recurse $targetdir -ErrorAction Continue `
    | where { $_.Name -EQ $name } `
    | foreach {
        echo-indented "Found $(hash $_) at $($_.FullName)"
        $_
    }

#Display objects we got Access Denies on:
$Error | ForEach-Object {
    Write-Host $_.TargetObject
}

Upvotes: 1

Related Questions