Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a list sorted lexicographically in a grid listed by column?

I have the result of Get-ChildItem, and I want to iterate over these, and display their names. By default if I simply use Write-Host then I get it listed out along the row like this:

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

However, say that I know I want it split into x columns, I want the output like this instead:

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

As you can see, it lists it down the columns first, and then across.

Any idea how to get output like that? Ideally it would use the most # of columns as can fit on screen with the Name aligned to the left in each column.

UPDATE: thanks to Roman, I can now have my linux style 'ls' output with directory colors. Building off his updated script I have:

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

Output:

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

like image 386
esac Avatar asked Nov 08 '10 17:11

esac


People also ask

How do you sort a list lexicographically?

Sorting Words in Lexicographic Order: So if we want to sort them lexicographically, we will compare the first alphabet of each word present in the list. As D is alphabetically smaller than P, the lexicographically sorted list will have ["DHONI", "PANT"].

How do you sort a lexicographically in Python?

Approach : Approach used in this program is very simple. Split the strings using split() function. After that sort the words in lexicographical order using sort(). Iterate the words through loop and print each word, which are already sorted.

What is lexicographic order example?

Lexicographical order is nothing but the dictionary order or preferably the order in which words appear in the dictonary. For example, let's take three strings, "short", "shorthand" and "small". In the dictionary, "short" comes before "shorthand" and "shorthand" comes before "small". This is lexicographical order.


1 Answers

It’s an interesting idea and task.

UPDATE: the updated script contains a few fixes and improvements. It also allows to customize the output in several ways. See examples in the script comments.

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"
}
like image 155
Roman Kuzmin Avatar answered Sep 28 '22 01:09

Roman Kuzmin