Private/Remove-DailyBackup.ps1

function Remove-DailyBackup
{
    <#
    .SYNOPSIS
        Removes old daily backup directories while keeping a specified number of recent backups.

    .DESCRIPTION
        Cleans up old daily backup directories by deleting the oldest backup folders first,
        while preserving a specified minimum number of recent backups. Only directories with
        date-formatted names (yyyy-MM-dd pattern) are considered for deletion. The function
        supports ShouldProcess for safe testing and will skip deletion if the number of
        existing backups doesn't exceed the retention limit.

    .PARAMETER Path
        The root directory path where daily backup folders are stored. This should be
        the parent directory containing date-named subdirectories (e.g., '2025-08-24').

    .PARAMETER BackupsToKeep
        The minimum number of backup directories to retain. Older backups beyond this
        number will be deleted. Must be a positive integer.

    .PARAMETER VerboseEnabled
        Controls whether verbose output is displayed during the cleanup operation.
        When $true, detailed information about the deletion process is shown.

    .INPUTS
        None. This function does not accept pipeline input.

    .OUTPUTS
        None. This function does not return any objects.

    .NOTES
        - Only directories matching the yyyy-MM-dd date pattern are processed
        - Backups are sorted by date (parsed from folder name) before deletion
        - Uses SupportsShouldProcess for WhatIf and Confirm support
        - Continues operation even if individual directory deletions fail
        - Skips cleanup if total backups don't exceed the retention limit

    .EXAMPLE
        PS > Remove-DailyBackup -Path 'C:\Backups' -BackupsToKeep 7 -VerboseEnabled $true

        Keeps the 7 most recent daily backup folders, removes older ones

    .EXAMPLE
        PS > Remove-DailyBackup -Path '/home/user/backups' -BackupsToKeep 3 -WhatIf

        Shows which backup directories would be deleted without actually removing them

    .EXAMPLE
        PS > Remove-DailyBackup -Path 'C:\DailyBackups' -BackupsToKeep 14

        Maintains a 2-week retention policy (14 days) for backup directories
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string] $Path,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [int] $BackupsToKeep,

        [Parameter(Mandatory = $false)]
        [bool] $VerboseEnabled = $false
    )

    $qualifiedBackupDirs = @(Get-ChildItem -LiteralPath $Path -Directory -ErrorAction 'SilentlyContinue' | Where-Object { $_.Name -match '^\d{4}-\d{2}-\d{2}$' })
    if ($qualifiedBackupDirs.Length -eq 0)
    {
        Write-Verbose ('New-DailyBackup:Remove-DailyBackup> No qualified backup directories to delete were detected in: {0}' -f $Path) -Verbose:$VerboseEnabled
        return
    }

    # Create a hashtable so we can sort backup directories based on their date-formatted folder name ('yyyy-MM-dd')
    $backups = @{ }
    foreach ($backupDir in $qualifiedBackupDirs)
    {
        $backups.Add($backupDir.FullName, [System.DateTime]$backupDir.Name)
    }

    $sortedBackupPaths = ($backups.GetEnumerator() | Sort-Object -Property Value | ForEach-Object { $_.Key })
    if ($sortedBackupPaths.Count -gt $BackupsToKeep)
    {
        for ($i = 0; $i -lt ($sortedBackupPaths.Count - $BackupsToKeep); $i++)
        {
            $backupPath = $sortedBackupPaths[$i]
            if ($PSCmdlet.ShouldProcess($backupPath, 'Remove backup directory'))
            {
                Write-Verbose ('New-DailyBackup:Remove-DailyBackup> Removing old backup directory: {0}' -f $backupPath) -Verbose:$VerboseEnabled
                Remove-ItemAlternative -LiteralPath $backupPath -WhatIf:$WhatIfPreference -Verbose:$VerboseEnabled
                Write-Verbose ('New-DailyBackup:Remove-DailyBackup> Successfully removed: {0}' -f $backupPath) -Verbose:$VerboseEnabled
            }
        }
    }
    else
    {
        Write-Verbose 'New-DailyBackup:Remove-DailyBackup> No surplus daily backups to delete' -Verbose:$VerboseEnabled
    }
}