PowerShell自定义函数输出格式化及排序问题咨询
PowerShell 文件/文件夹大小格式化优化方案
我编写了多个类似如下的简易PowerShell函数(用于以易读格式输出文件/文件夹大小及名称),现需要解决三个格式化问题:
- 让大小列右对齐、文件/文件夹名列左对齐
- 替换制表符
t,根据大小列的最大宽度(含[DIR]行)设置列宽,使其比最大宽度大2个字符 - 让目录优先排序
原函数代码
function d ($name) { # quick and dirty Size + Name $out = "" function Format-FileSize([int64]$size) { if ($size -gt 1TB) {[string]::Format("{0:0.00} TB", $size / 1TB)} elseif ($size -gt 1GB) {[string]::Format("{0:0.0} GB", $size / 1GB)} elseif ($size -gt 1MB) {[string]::Format("{0:0.0} MB", $size / 1MB)} elseif ($size -gt 1KB) {[string]::Format("{0:0.0} KB", $size / 1KB)} elseif ($size -gt 0) {[string]::Format("{0:0.0} B", $size)} else {""} } foreach ($i in (gci $folder | sort Length).FullName) { if (Test-Path -Path $i -PathType Container) { $size = "[DIR]" $size_out = "[DIR]" } else { $size = (gci $i | select Length).Length $size_out = Format-FileSize($size) $size_total += $size } $out += "$size_out`t$(split-path $i -leaf)`n" } $out += "========`n$(Format-FileSize($size_total)) Total Size" $out }
期望输出示例
[DIR] 0 [DIR] Setup [DIR] Stuff 69.0 B Profiler.url 480.0 B test-countdown.ps1 1.0 KB PinToTaskbar.ps1 3.5 KB Firefox2.reg 70.5 KB Firefox1.reg 124.7 KB elevate.exe 9.2 MB Stardock Fences 4.0.0.3.exe 112.5 MB pandoc.exe 12.1 GB image.iso ======== 12.2 GB Total Size
优化后的完整函数
function d ($folder = ".") { # 定义大小格式化函数 function Format-FileSize([int64]$size) { switch ($size) { { $_ -gt 1TB } { return "{0:0.00} TB" -f ($_ / 1TB) } { $_ -gt 1GB } { return "{0:0.0} GB" -f ($_ / 1GB) } { $_ -gt 1MB } { return "{0:0.0} MB" -f ($_ / 1MB) } { $_ -gt 1KB } { return "{0:0.0} KB" -f ($_ / 1KB) } { $_ -gt 0 } { return "{0:0.0} B" -f $_ } default { return "" } } } # 获取所有文件和目录,先按是否是目录排序(目录在前),再按大小排序 $items = Get-ChildItem -Path $folder | Sort-Object -Property @{Expression='PSIsContainer'; Descending=$true}, Length # 收集所有大小显示文本(包括[DIR]和总计),用于计算最大宽度 $sizeStrings = @() $totalSize = 0 foreach ($item in $items) { if ($item.PSIsContainer) { $sizeStrings += "[DIR]" } else { $sizeStrings += Format-FileSize $item.Length $totalSize += $item.Length } } $sizeStrings += Format-FileSize $totalSize # 计算大小列宽度:最大字符串长度 + 2 $sizeColumnWidth = ($sizeStrings | Measure-Object -Property Length -Maximum).Maximum + 2 # 生成输出内容 $output = @() foreach ($item in $items) { $sizeText = $item.PSIsContainer ? "[DIR]" : Format-FileSize $item.Length # 大小列右对齐,名称列左对齐 $outputLine = "{0, -$sizeColumnWidth} {1}" -f $sizeText.PadLeft($sizeColumnWidth - 2), $item.Name $output += $outputLine } # 添加分隔线和总计行 $output += "=" * ($sizeColumnWidth + 2 + (Get-ChildItem $folder | Select-Object -First 1 -ExpandProperty Name | Measure-Object -Property Length -Maximum).Maximum) $totalSizeText = Format-FileSize $totalSize $output += "{0, -$sizeColumnWidth} Total Size" -f $totalSizeText.PadLeft($sizeColumnWidth - 2) # 输出结果 $output -join "`n" }
问题解决说明
1. 大小列右对齐、名称列左对齐
使用PowerShell格式化运算符 -f 结合 PadLeft() 方法实现:
$sizeText.PadLeft($sizeColumnWidth - 2)将大小文本填充到指定宽度,实现右对齐- 格式化字符串
"{0, -$sizeColumnWidth} {1}"中的-标记确保名称列靠左显示
2. 动态设置列宽
- 先收集所有需要显示的大小文本(包括[DIR]和总计大小),用
Measure-Object计算最长字符串的长度 - 列宽设为最大长度 + 2,预留足够留白
- 替换原制表符
t,改用计算好的列宽进行格式化输出
3. 目录优先排序
修改 Sort-Object 的排序规则,先按 PSIsContainer 属性降序排列(目录为$true,会排在前面),再按文件大小排序:
Sort-Object -Property @{Expression='PSIsContainer'; Descending=$true}, Length
内容的提问来源于stack exchange,提问作者YorSubs
相关产品推荐
相关产品推荐

