public/Export-Bucket.ps1
|
function Export-Bucket { <# .SYNOPSIS Exports a bucket to a single archive file. .DESCRIPTION Serializes all objects in a bucket to a single JSON or CLIXML archive file. Includes object metadata (_BucketName, _BucketKey) for easy restoration. Default format is JSON. Use -AsBinary for CLIXML/PSSerializer format with full .NET type preservation. .PARAMETER Bucket Bucket name to export. Supports wildcards. .PARAMETER Path Root directory for bucket storage. Default: $HOME/.buckets. .PARAMETER OutputFile Path to the output archive file. .PARAMETER AsBinary Export as CLIXML/PSSerializer binary archive (default is JSON). .PARAMETER Compress Enable GZip compression for CLIXML archives. Only effective with -AsBinary. .PARAMETER Recurse Recurse into nested sub-buckets. Without this switch, only exports objects from the specified bucket directory. .PARAMETER Depth Maximum nesting depth when recursing. Default: unlimited. .PARAMETER Quiet Suppress all output. .EXAMPLE Export-Bucket -Bucket users -OutputFile "./users-backup.json" .EXAMPLE Export-Bucket -Bucket "config*" -OutputFile "./config-backup.clixml" -AsBinary #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)][string[]]$Bucket, [string]$Path, [Parameter(Mandatory = $true)][string]$OutputFile, [switch]$AsBinary, [switch]$Compress, [switch]$Recurse, [int]$Depth = [int]::MaxValue, [switch]$Quiet ) if ([string]::IsNullOrWhiteSpace($Path)) { $Path = Get-DefaultPath } $Path = Resolve-SafePath -Path $Path $allObjects = [System.Collections.ArrayList]::new() $exportedBuckets = 0 $exportedObjects = 0 foreach ($b in $Bucket) { $objects = Get-BucketObject -Bucket $b -Path $Path -Recurse:$Recurse -Depth $Depth if ($objects) { $null = $allObjects.AddRange(@($objects)) $exportedBuckets++ $exportedObjects += @($objects).Count } } if ($allObjects.Count -eq 0) { Write-Warning "No objects found to export for buckets: $($Bucket -join ', ')" return } $outputDir = [System.IO.Path]::GetDirectoryName((Resolve-SafePath -Path $OutputFile)) if (-not [System.IO.Directory]::Exists($outputDir)) { $null = [System.IO.Directory]::CreateDirectory($outputDir) } if ($AsBinary) { $xml = [System.Management.Automation.PSSerializer]::Serialize($allObjects, 10) $rawBytes = [System.Text.Encoding]::UTF8.GetBytes($xml) if ($Compress) { $ms = [System.IO.MemoryStream]::new() try { $cs = [System.IO.Compression.GZipStream]::new($ms, [System.IO.Compression.CompressionLevel]::Optimal) try { $cs.Write($rawBytes, 0, $rawBytes.Length) } finally { $cs.Close() } [System.IO.File]::WriteAllBytes($OutputFile, $ms.ToArray()) } finally { $ms.Dispose() } } else { [System.IO.File]::WriteAllBytes($OutputFile, $rawBytes) } } else { $json = ConvertTo-Json -InputObject $allObjects -Depth 20 -Compress [System.IO.File]::WriteAllText($OutputFile, $json, [System.Text.Encoding]::UTF8) } if (-not $Quiet) { $bucketArg = if ($Bucket -is [array]) { $Bucket -join ', ' } else { $Bucket } Write-Host "$bucketArg" -NoNewline -ForegroundColor $script:CPath Write-Host " · " -NoNewline -ForegroundColor $script:CMuted Write-Host $exportedObjects -NoNewline -ForegroundColor $script:CNum Write-Host " objects → " -NoNewline -ForegroundColor $script:CMuted Write-Host "$([System.IO.Path]::GetFileName($OutputFile))" -ForegroundColor $script:CAction } } |