Powershell 如何在按列列出的网格中编写按词典排序的列表?

Powershell 如何在按列列出的网格中编写按词典排序的列表?,powershell,directory,get-childitem,Powershell,Directory,Get Childitem,我得到了getchilditem的结果,我想迭代这些结果,并显示它们的名称。默认情况下,如果我只使用Write Host,那么我会将它沿着行列出,如下所示: PerfLogs Program Files Program Files (x86) Python31 Temp Users Windows 但是,假设我希望将其拆分为x列,我希望输出如下: PerfLogs Python31 Windows Program Files

我得到了
getchilditem
的结果,我想迭代这些结果,并显示它们的名称。默认情况下,如果我只使用
Write Host
,那么我会将它沿着行列出,如下所示:

PerfLogs  Program Files  Program Files (x86)  Python31  Temp  Users  Windows
但是,假设我希望将其拆分为x列,我希望输出如下:

PerfLogs                  Python31     Windows
Program Files             Temp
Program Files (x86)       Users
如您所见,它首先在列中列出它,然后在列之间列出它

你知道如何获得这样的输出吗?理想情况下,它将使用屏幕上最多的列,每个列的名称都与左边对齐

更新:多亏了Roman,我现在可以用目录颜色输出linux风格的“ls”。根据他的更新脚本,我有:

function color-ls
{
    dir $args | Format-High -Print {    
        $item = $args
        $fore = $host.UI.RawUI.ForegroundColor        
        $host.UI.RawUI.ForegroundColor = .{     
            if ($item[1].psIsContainer) {'Blue'}
            elseif ($item[1].Extension -match '\.(exe|bat|cmd|ps1|psm1|vbs|rb|reg|dll|o|lib)') {'Red'}
            elseif ($item[1].Extension -match '\.(zip|tar|gz|rar)') {'Yellow'}
            elseif ($item[1].Extension -match '\.(py|pl|cs|rb|h|cpp)') {'Cyan'}
            elseif ($item[1].Extension -match '\.(txt|cfg|conf|ini|csv|log|xml)') {'Green'}
            else {$fore}
        }
        write-host $args[0] -NoNewLine
        $host.UI.RawUI.ForegroundColor = $fore
    }
}
输出:


这是一个有趣的想法和任务

更新:更新后的脚本包含一些修复和改进。它还允许以多种方式自定义输出。请参见脚本注释中的示例

脚本格式-High.ps1:

<#
.SYNOPSIS
    Formats input by columns using maximum suitable column number.

.DESCRIPTION
    Format-High prints the specified property, expression, or string
    representation of input objects filling the table by columns.

    It is named in contrast to Format-Wide which prints by rows.

.EXAMPLE
    # just items
    ls c:\windows | Format-High

    # ditto in colors based on PSIsContainer
    ls c:\windows | Format-High -Print {$c = if ($args[1].PSIsContainer) {'yellow'} else {'white'}; Write-Host $args[0] -ForegroundColor $c -NoNewline}

    # just processes, not good
    ps | Format-High

    # process names, much better
    ps | Format-High Name

    # custom expression and width
    ps | Format-High {$_.Name + ':' + $_.WS} 70

    # process names in colors based on working sets
    ps | Format-High Name 70 {$c = if ($args[1].WS -gt 10mb) {'red'} else {'green'}; Write-Host $args[0] -ForegroundColor $c -NoNewline}
#>

param
(
    [object]$Property,
    [int]$Width = $Host.UI.RawUI.WindowSize.Width - 1,
    [scriptblock]$Print = { Write-Host $args[0] -NoNewline },
    [object[]]$InputObject
)

# process the input, get strings to format
if ($InputObject -eq $null) { $InputObject = @($input) }
if ($Property -is [string]) { $strings = $InputObject | Select-Object -ExpandProperty $Property }
elseif ($Property -is [scriptblock]) { $strings = $InputObject | ForEach-Object $Property }
else { $strings = $InputObject }
$strings = @(foreach($_ in $strings) { "$_" })

# pass 1: find the maximum column number
$nbest = 1
$bestwidths = @($Width)
for($ncolumn = 2; ; ++$ncolumn) {
    $nrow = [Math]::Ceiling($strings.Count / $ncolumn)
    $widths = @(
        for($s = 0; $s -lt $strings.Count; $s += $nrow) {
            $e = [Math]::Min($strings.Count, $s + $nrow)
            ($strings[$s .. ($e - 1)] | Measure-Object -Maximum Length).Maximum + 1
        }
    )
    if (($widths | Measure-Object -Sum).Sum -gt $Width) {
        break
    }
    $bestwidths = $widths
    $nbest = $ncolumn
    if ($nrow -le 1) {
        break
    }
}

# pass 2: print strings
$nrow = [Math]::Ceiling($strings.Count / $nbest)
for($r = 0; $r -lt $nrow; ++$r) {
    for($c = 0; $c -lt $nbest; ++$c) {
        $i = $c * $nrow + $r
        if ($i -lt $strings.Count) {
            & $Print ($strings[$i].PadRight($bestwidths[$c])) $InputObject[$i]
        }
    }
    & $Print "`r`n"
}

param
(
[对象]$Property,
[int]$Width=$Host.UI.RawUI.WindowSize.Width-1,
[scriptblock]$Print={写入主机$args[0]-NoNewline},
[object[]]$InputObject
)
#处理输入,获取要格式化的字符串
如果($InputObject-eq$null){$InputObject=@($input)}
如果($Property-is[string]){$strings=$InputObject |选择对象-ExpandProperty$Property}
elseif($Property-is[scriptblock]){$strings=$InputObject | ForEach Object$Property}
else{$strings=$InputObject}
$strings=@(foreach($\在$strings中){“$\})
#第1步:查找最大列数
$nbest=1
$bestwidths=@($Width)
对于($ncolumn=2;;++$ncolumn){
$nrow=[Math]::上限($strings.Count/$ncolumn)
$widths=@(
对于($s=0;$s-lt$strings.Count;$s+=$nrow){
$e=[Math]::Min($strings.Count,$s+$nrow)
($strings[$s..$e-1)]|测量对象-最大长度。最大值+1
}
)
如果($widths |测量对象-求和)。求和-gt$Width){
打破
}
$bestwidths=$widths
$nbest=$n列
如果($nrow-le 1){
打破
}
}
#过程2:打印字符串
$nrow=[Math]::上限($strings.Count/$nbest)
对于($r=0;$r-lt$nrow;++$r){
对于($c=0;$c-lt$nbest;++$c){
$i=$c*$nrow+$r
如果($i-lt$strings.Count){
&$Print($strings[$i].PadRight($bestwidths[$c]))$InputObject[$i]
}
}
&$Print“`r`n”
}

同意排序,这太好了。我正在学习powershell,你能告诉我,{}在$widths=.{}中做了什么吗?在宽度总和之后,它应该是$bestwidths=($widths)。。如果只有一个文件,它会抛出异常。
{}
是点运算符(在当前范围内调用)+它调用的脚本块。但是在本例中,有一个更好的构造
@()
,它也修复了您注意到的错误。我将很快更新代码(还有其他一些小缺陷)。知道目录中没有文件时为什么会挂起吗?一个bug。我已经更新了代码:将
if($nrow-eq 1)
替换为
if($nrow-le 1)
。我很高兴您以其设计的方式重新使用了更新后的脚本。谢谢你的灵感。如果PowerShell具有此内置功能,那就太好了,我已经提交了建议:在哪里放置
格式高.ps1
?我尝试了
C:\Users\X\Documents\WindowsPowerShell\Scripts\Format High.ps1
,也尝试了与我的配置文件相同的目录,其中包含
color ls
,即
C:\Users\X\Documents\WindowsPowerShell\Microsoft.PowerShell\u profile.ps1
,但我得到了一个错误
术语“Format High.ps1”无法识别。