Public/Copy-sqmNTFSPermissions.ps1

<#
.SYNOPSIS
    Copies NTFS permissions (ACLs) from a source path to a destination path.

.DESCRIPTION
    Reads the explicit NTFS permissions for each file system object (folder/file) below
    the source path and applies them to the corresponding object below the destination path.
    The target structure must already exist (exception: with -CreateMissingFolders, missing
    target folders are created automatically).

.PARAMETER SourcePath
    Source path (e.g. "D:\" or "D:\Data").

.PARAMETER DestinationPath
    Destination path (e.g. "E:\" or "E:\Data").

.PARAMETER Recurse
    Recursive traversal of all subfolders and files.

.PARAMETER CreateMissingFolders
    Automatically creates missing target folders (directories only, not files).
    Files missing at the destination are skipped.

.PARAMETER IncludeSystemAndHidden
    Includes hidden and system objects in the processing.

.EXAMPLE
    Copy-sqmNTFSPermissions -SourcePath "D:\" -DestinationPath "E:\" -Recurse
    Copies all permissions from D: to E: (recursively).

.EXAMPLE
    Copy-sqmNTFSPermissions -SourcePath "D:\Daten" -DestinationPath "E:\Daten" -Recurse -CreateMissingFolders
    Copies permissions and creates missing target folders.

.NOTES
    Requires administrative rights (Get-Acl / Set-Acl).
    Access errors generate warnings; processing continues.
#>

function Copy-sqmNTFSPermissions {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateScript({ Test-Path $_ -PathType Container })]
        [string]$SourcePath,

        [Parameter(Mandatory = $true, Position = 1)]
        [string]$DestinationPath,

        [switch]$Recurse,
        [switch]$CreateMissingFolders,
        [switch]$IncludeSystemAndHidden
    )

    begin {
        $DestinationPath = [System.IO.Path]::GetFullPath($DestinationPath)
        if (-not (Test-Path -LiteralPath $DestinationPath -PathType Container)) {
            if ($CreateMissingFolders) {
                if ($PSCmdlet.ShouldProcess($DestinationPath, "Erstelle Zielverzeichnis")) {
                    New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null
                    Write-Verbose "Zielverzeichnis '$DestinationPath' wurde erstellt."
                }
            } else {
                throw "Zielpfad '$DestinationPath' existiert nicht. Verwenden Sie -CreateMissingFolders."
            }
        }

        if ($Recurse) {
            $allItems = @(Get-Item -Path $SourcePath -Force:$IncludeSystemAndHidden) +
                        @(Get-ChildItem -Path $SourcePath -Recurse -Force:$IncludeSystemAndHidden -ErrorAction SilentlyContinue)
        } else {
            $allItems = @(Get-Item -Path $SourcePath -Force:$IncludeSystemAndHidden)
        }

        $total   = $allItems.Count
        $current = 0
    }

    process {
        foreach ($sourceItem in $allItems) {
            $current++
            $relativePath = $sourceItem.FullName.Substring($SourcePath.TrimEnd('\').Length).TrimStart('\')
            $destItemPath = Join-Path -Path $DestinationPath -ChildPath $relativePath

            Write-Progress -Activity "Kopiere NTFS-Berechtigungen" `
                           -Status "$current von $total : $relativePath" `
                           -PercentComplete (($current / $total) * 100)

            if ($sourceItem.PSIsContainer) {
                if (-not (Test-Path -LiteralPath $destItemPath -PathType Container)) {
                    if ($CreateMissingFolders) {
                        if ($PSCmdlet.ShouldProcess($destItemPath, "Erstelle Ordner")) {
                            try {
                                New-Item -ItemType Directory -Path $destItemPath -Force -ErrorAction Stop | Out-Null
                                Write-Verbose "Ordner '$destItemPath' erstellt."
                            } catch {
                                Write-Warning "Fehler beim Erstellen von '$destItemPath': $($_.Exception.Message)"
                                continue
                            }
                        }
                    } else {
                        Write-Warning "Zielordner '$destItemPath' existiert nicht. Ueberspringe (-CreateMissingFolders verwenden)."
                        continue
                    }
                }
            } else {
                if (-not (Test-Path -LiteralPath $destItemPath -PathType Leaf)) {
                    Write-Warning "Zieldatei '$destItemPath' existiert nicht. Ueberspringe."
                    continue
                }
            }

            try {
                $acl = Get-Acl -Path $sourceItem.FullName -ErrorAction Stop
                if ($PSCmdlet.ShouldProcess($destItemPath, "Setze ACL von '$($sourceItem.FullName)'")) {
                    Set-Acl -Path $destItemPath -AclObject $acl -ErrorAction Stop
                    Write-Verbose "ACL kopiert: $relativePath"
                }
            } catch {
                Write-Warning "Fehler bei '$($sourceItem.FullName)' -> '$destItemPath': $($_.Exception.Message)"
            }
        }
        Write-Progress -Activity "Kopiere NTFS-Berechtigungen" -Completed
    }

    end {
        Write-Host "Abgeschlossen. $total Elemente verarbeitet." -ForegroundColor Green
    }
}