public/Get-BucketObjectStats.ps1
|
function Get-BucketObjectStats { <# .SYNOPSIS Returns detailed per-object statistics for objects in a bucket. .DESCRIPTION Enumerates objects and reads lightweight metadata (format, size, type, timestamps, compression status) without full deserialization. Peeks at file content to determine object type (Object, Array, or Value) from the first bytes. .PARAMETER Bucket Bucket name to scan. If omitted, scans all buckets under -Path. Supports wildcards. .PARAMETER Key Exact object key to look up. When specified, returns stats for a single object only. .PARAMETER Path Root directory for bucket storage. Default: $HOME/.buckets. .PARAMETER Match Filter keys by pattern (wildcard). Case-insensitive. .OUTPUTS PSCustomObject with Bucket, Key, Format, Type, Size, LastWriteTime, and IsCompressed properties. Path is included as a hidden property. .EXAMPLE Get-BucketObjectStats -Bucket users .EXAMPLE Get-BucketObjectStats -Bucket users -Match "*admin*" .EXAMPLE Get-BucketObjectStats -Bucket users -Key "alice" #> [CmdletBinding()] param( [Parameter(Position = 0)][string]$Bucket, [Parameter(Position = 1)][string]$Key, [string]$Path, [string]$Match ) if ([string]::IsNullOrWhiteSpace($Path)) { $Path = Get-DefaultPath } $Path = Resolve-SafePath -Path $Path $bucketPaths = @() if (-not [string]::IsNullOrWhiteSpace($Bucket)) { if ($Bucket -match '[\*\?]') { $cachedBuckets = Get-Bucket -Path $Path -Recurse $matched = $cachedBuckets | Where-Object { $_.Name -like $Bucket } $bucketPaths += $matched | ForEach-Object { $_.Path } } else { $bucketPaths += Get-BucketPath -Name $Bucket -Path $Path } } else { if ([System.IO.Directory]::Exists($Path)) { $bucketPaths += [System.IO.DirectoryInfo]::new($Path).GetDirectories() | ForEach-Object { $_.FullName } } } $results = [System.Collections.ArrayList]::new() foreach ($bucketPath in $bucketPaths) { if (-not [System.IO.Directory]::Exists($bucketPath)) { continue } $bucketName = $bucketPath.Substring($Path.Length).TrimStart([System.IO.Path]::DirectorySeparatorChar).Replace([System.IO.Path]::DirectorySeparatorChar, '/') $di = [System.IO.DirectoryInfo]::new($bucketPath) if (-not [string]::IsNullOrWhiteSpace($Key)) { $jsonFile = [System.IO.Path]::Combine($bucketPath, "$Key.json") $datFile = [System.IO.Path]::Combine($bucketPath, "$Key.dat") $found = $false foreach ($filePath in @($datFile, $jsonFile)) { if ([System.IO.File]::Exists($filePath)) { $f = [System.IO.FileInfo]::new($filePath) $info = Resolve-ObjectType -FileInfo $f $entry = [PSCustomObject]@{ Bucket = $bucketName Key = $Key Format = if ($f.Extension -eq ".json") { "JSON" } else { "Binary" } Type = $info.Type Size = $f.Length LastWriteTime = $f.LastWriteTime IsCompressed = $info.IsCompressed } Add-HiddenProperty -Target $entry -Name 'Path' -Value $f.FullName $null = $results.Add($entry) $found = $true break } } if (-not $found) { Write-Warning "Key '$Key' not found in bucket '$bucketName'" } continue } $files = @($di.GetFiles("*.json")) + @($di.GetFiles("*.dat")) foreach ($f in $files) { $fKey = [System.IO.Path]::GetFileNameWithoutExtension($f.Name) if (-not [string]::IsNullOrWhiteSpace($Match) -and $fKey -notlike $Match) { continue } $info = Resolve-ObjectType -FileInfo $f $entry = [PSCustomObject]@{ Bucket = $bucketName Key = $fKey Format = if ($f.Extension -eq ".json") { "JSON" } else { "Binary" } Type = $info.Type Size = $f.Length LastWriteTime = $f.LastWriteTime IsCompressed = $info.IsCompressed } Add-HiddenProperty -Target $entry -Name 'Path' -Value $f.FullName $null = $results.Add($entry) } } $results } |