functions/Test-ExcludedFiles.ps1

function Test-ExcludedFiles {
<#
.SYNOPSIS
Returns a list of files excluded based on patterns defined in an exclude-files.json file.
 
.DESCRIPTION
This function reads exclusion patterns from an `exclude-files.json` file and returns all files under the given module path that match these patterns. Patterns can match full file paths or entire directories. Matching is based on relative paths with forward slashes (`/`).
 
.PARAMETER ModulePath
The root path of the module to scan for files. Defaults to the script's location.
 
.PARAMETER ExcludeFileName
The name of the JSON file that contains the exclusion patterns. Defaults to 'exclude-files.json'.
 
.OUTPUTS
An array of fully qualified file paths that match the exclusion patterns.
 
.EXAMPLE
Test-ExcludedFiles -ModulePath "C:\MyModule"
 
Returns all files in `C:\MyModule` that match the exclusion rules in `exclude-files.json`.
 
.NOTES
• Exclusion patterns should use forward slashes (`/`) and be relative to the module root.
• Patterns ending with `/` are treated as directory exclusions.
#>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)]
        [string] $ModulePath = $PSScriptRoot,

        [Parameter(Mandatory = $false)]
        [string] $ExcludeFileName = "exclude-files.json"
    )

    $ModulePath = (Resolve-Path -Path $ModulePath -ErrorAction Stop).Path
    $excludeFilePath = (Resolve-Path -Path $ExcludeFileName -ErrorAction Stop).Path

    if (-not (Test-Path $excludeFilePath)) {
        Write-Warning "Exclude file not found: $excludeFilePath"
        return
    }

    try {
        $patterns = Get-Content $excludeFilePath -Raw | ConvertFrom-Json
    } catch {
        Write-Warning "Fehler beim Lesen der Datei $($excludeFilePath): $_"
        return
    }

    if (-not $patterns -or $patterns.Count -eq 0) {
        Write-Warning "Keine Ausschlussmuster definiert in $excludeFilePath"
        return
    }

    $allFiles = Get-ChildItem -Path $ModulePath -Recurse -File

    $allFilesRelative = $allFiles | ForEach-Object {
        $relPath = $_.FullName.Substring($ModulePath.Length).TrimStart('\','/')
        $relPath -replace '\\','/'
    }

    $excludedFiles = @()

    foreach ($pattern in $patterns) {
        $patternNormalized = $pattern.Trim()

        if ($patternNormalized.EndsWith('/')) {
            # Ausschluss für komplettes Verzeichnis
            $excludedMatchList = $allFilesRelative | Where-Object { $_.StartsWith($patternNormalized) }
        } else {
            # Exakter Pfadvergleich
            $excludedMatchList = $allFilesRelative | Where-Object { $_ -eq $patternNormalized }
        }

        foreach ($match in $excludedMatchList) {
            $fullPath = Join-Path -Path $ModulePath -ChildPath ($match -replace '/','\')
            $excludedFiles += $fullPath
        }
    }

    $excludedFiles = $excludedFiles | Sort-Object -Unique

    Write-Verbose "Ausschlussmuster aus $($excludeFilePath):"
    foreach ($p in $patterns) {
        Write-Verbose " - $p"
    }

    Write-Verbose ""
    Write-Verbose "Gefundene auszuschließende Dateien:"
    if ($excludedFiles.Count -eq 0) {
        Write-Verbose " (keine Dateien ausgeschlossen)"
    } else {
        foreach ($file in $excludedFiles) {
            Write-Verbose " $file"
        }
    }

    return $excludedFiles
}