Recursively find all the files that match a mask, with exclusion criteria.

<#
.SYNOPSIS
    Recursively find all the files that match a mask.

.DESCRIPTION
    Why not simply cal Get-ChildItem -Recurse ...?
    Traversing the many directories that are full of junk we're not interested
    can take a long time. Unlike 'Get-ChildItem', this function does not
    traverse directories that match the '-AntiMasks'.

.PARAMETER Path
    Start searching from where? Defaults to the current directory.

.PARAMETER Masks
    A list of masks to match against the files.

.PARAMETER MaxDepth
    How deep should we look into subdirectories?  Default is no limit.

.PARAMETER AntiMasks
    Stop recursing when we reach a directory with a matching name.

.EXAMPLE
    Find-Files -Masks *.txt
#>
function Find-Files(
    $Path = $null,
    [string[]]$Masks = '*',
    $MaxDepth = -1,
    $Depth = 0,
    [string[]]$AntiMasks = @('bin', 'obj', 'packages', '.git')
) {
    foreach ($item in Get-ChildItem $Path | Sort-Object -Property Mode, Name) {
        if ($Masks | Where-Object { $item -like $_ }) {
            $item.FullName
        }
        if ($AntiMasks | Where-Object { $item -like $_ }) {
            # Do not recurse.
        }
        elseif ($MaxDepth -ge 0 -and $Depth -ge $MaxDepth) {
            # We have reached the max depth.  Do not recurse.
        }
        elseif (Test-Path $item.FullName -PathType Container) {
            Find-Files $item.FullName $Masks $MaxDepth ($Depth + 1) $AntiMasks
        }
    }
}