2010-11-08 3 views
5

Ich habe das Ergebnis Get-ChildItem, und ich möchte über diese iterieren und ihre Namen anzeigen. Standardmäßig einfach, wenn ich Write-Host verwenden dann bekomme ich es entlang der Zeile wie folgt aufgelistet out:Wie schreibe ich eine Liste lexikographisch in einem Raster sortiert nach Spalten?

PerfLogs Program Files Program Files (x86) Python31 Temp Users Windows 

jedoch sagen, dass ich weiß, ich will es in x Spalten aufgeteilt, ich die Ausgabe so wollen statt:

PerfLogs     Python31  Windows 
Program Files    Temp 
Program Files (x86)  Users 

Wie Sie sehen können, listet es die Spalten zuerst und dann quer auf.

Irgendeine Idee, wie man so ausgegeben wird? Idealerweise würde es die meisten # Spalten verwenden, die auf den Bildschirm passen, wobei der Name in jeder Spalte nach links ausgerichtet ist.

UPDATE: Dank Roman, kann ich jetzt meine Linux-Stil 'ls' Ausgabe mit Verzeichnisfarben. Aufbauend auf seiner aktualisierten Skript Ich habe:

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 
    } 
} 

Ausgang:

http://dl.dropbox.com/u/2809/lscolor.png

+0

Ich bin froh, dass Sie das aktualisierte Skript genau in einer Art und Weise wiederverwendet es für entworfen wurde. Danke für die inspirierende Idee. Es wäre schön, wenn PowerShell dies eingebaut hat, habe ich den Vorschlag eingereicht: https://connect.microsoft.com/PowerShell/feedback/details/620452/format-wide-add-an-option-to-output -von-Spalten –

Antwort

6

Es ist eine interessante Idee und Aufgabe.

UPDATE: Das aktualisierte Skript enthält einige Korrekturen und Verbesserungen. Es erlaubt auch, die Ausgabe auf verschiedene Arten anzupassen. Siehe Beispiele in den Skriptkommentaren.

Script Format-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" 
} 
+0

Vereinbart auf die Sortierung, das ist verdammt gut. Ich lerne nur Powershell, kannst du mich auf das hinweisen, was die. {} In $ widths =. {} Tut? – esac

+0

nach der Summe der Breiten, sollte es $ bestwidths = ($ Breiten) sein .. wenn es nur eine Datei gibt, löst es eine Ausnahme aus. – esac

+0

'. {}' Ist der Operator * dot * (Aufruf im aktuellen Bereich) + der Scriptblock, der von ihm aufgerufen wird. Aber in diesem Fall gibt es ein besseres Konstrukt '@()', das auch den Fehler behebt, den Sie bemerkt haben. Ich werde den Code bald aktualisieren (es gibt noch andere kleinere Fehler). –

Verwandte Themen