5

I'm looking for a way to recursively go through my entire file share ( fairly large 3TB of files ) and list out all files/folders that I don't have access to. Due to a migration and some errors on large paths ( more than 255 characters ) we've found some folders/files have lost all permissions, and need a way to find them all. Currently as a domain admin user, I can't list the permissions or owner. I can take control of it, and reset the permissions, but I have so many files/folders I'd like to output this to a CSV files or something.

I've tried the following :

get-childitem "\,\fileshare\f$\folder\etc" -recurse | get-acl

This seems to work perfectly, it gives me the ACLs of all the files/folders that exist and have proper permissions on them. But once it hits a folder that I don't have access to, I get the following error :

Get-Acl : Attempted to perform an unauthorized operation.
At line:1 char:133
+ get-childitem "\,\fileshare\f$\folder\etc" -re
curse | get-acl <<<<
    + CategoryInfo          : NotSpecified: (:) [Get-Acl], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetAclCommand

These are the errors I'd like to log to a CSV/TXT file, and ignore all the rest of the permissions, it would be ideal if this could be outputted in more one line per error fashion as well.

Just wondering if anyone has an idea or hint on how I should proceed?

(Please note the paths above have commas in them on purpose to not resolve to a real path

\,\fileshare\f$\folder\etc)

Thanks!

2 Answers 2

2

An easier and less confusing way to trap cmdlet specific errors to a file is by using the -Errorvariable parameter. It is built into most cmdlets. It is not reliable to look at the $Error variable as it is a global variable and has a high chance of being stained by other unmitigated errors in the powershell process.

The code below will log the errors in 2 log files.

  1. gci_errors.csv - Contains errors enumerating the folders
  2. gacl_errors.csv - Contains errors enumerating ACL on a particular file/folder.

    Get-ChildItem C:\Temp -Recurse -ErrorAction SilentlyContinue -ErrorVariable gci_errors | ForEach-Object {
    
        $_ | Get-Acl -ErrorAction SilentlyContinue -ErrorVariable gacl_errors
    }
    
    $gci_errors | Select-Object -ExpandProperty CategoryInfo | Export-Csv -NoTypeInformation -Path C:\Temp\gci_errors.csv 
    $gacl_errors | Select-Object -ExpandProperty CategoryInfo | Export-Csv -NoTypeInformation -Path C:\Temp\gacl_errors.csv
    

I have changed the output to a CSV file as per your requirement. It makes more sense as its easier to analyse and import to run commands on the data. The CSV has a colum header called Target which reflects the folder path that is causing you problems. You can write a cmdlet ie Fix-DirPerms and pipe to it. Something like:

    Import-CSV -Path c:\Temp\gci_errors.csv | Fix-DirPerms
1

There are a lot of different ways to do this. Here is something I just cooked up.

$Error.Clear()      # This is a global variable!
$Errors = @()
$Items = Get-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue
ForEach($Err In $Error)
{
    $Errors += $Err.Exception
}
ForEach($Item In $Items)
{
    Try
    {
        $Item | Get-ACL -ErrorAction SilentlyContinue | Out-Null
    }
    Catch
    {
        $Errors += "$($_.Exception.Message) $($Item.FullName)"
    }
}    
Write-Host $Errors.Count "errors encountered."
$Errors | Out-File errors.txt

So now you have a neat list of all the errors that were encountered either in the Get-ChildItem process or in the Get-ACL process, which is important because distinct errors can be encountered during each operation. You can pipe the $Errors variable out to a CSV or whatever you want. This will probably take a long time to run on a 3TB network share. Consider adding a progress meter.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .