在 Powershell 中模拟 `ls`

Mar*_*eed 5 powershell

我正在尝试ls在 PowerShell 中获得类似于 UNIX输出的内容。这是到达那里:

Get-ChildItem | Format-Wide -AutoSize -Property Name
Run Code Online (Sandbox Code Playgroud)

但它仍然以行优先而不是列优先顺序输出项目:

PS C:\Users\Mark Reed> Get-ChildItem | Format-Wide -AutoSize -Property Name

Contacts      Desktop       Documents     Downloads    Favorites    
Links         Music         Pictures      Saved Games
Searches      Videos
Run Code Online (Sandbox Code Playgroud)

期望的输出:

PS C:\Users\Mark Reed> My-List-Files 

Contacts        Downloads       Music           Searches
Desktop         Favorites       Pictures        Videos
Documents       Links           Saved Games 
Run Code Online (Sandbox Code Playgroud)

不同之处在于排序:1 2 3 4 5/6 7 8 9 跨行阅读,而 1/2/3 4/5/6 7/8/9 阅读各列。

我已经有了一个脚本,它可以使用一个数组并以列主要顺序打印出来Write-Host,尽管我通过阅读 Keith 和 Roman 的文章发现了很多 PowerShellish 惯用的改进。但我从阅读中得出的印象是,这是错误的方法。Write-Host脚本应该输出对象,而不是调用,并让格式化程序和输出程序负责将正确的内容写入用户控制台。

当脚本使用 时Write-Host,它的输出是不可捕获的;如果我将结果分配给一个变量,我会得到一个空变量,并且无论如何输出都会写入屏幕。这就像 UNIX 管道中间的命令直接写入/dev/tty而不是标准输出甚至标准错误。

诚然,我可能无法Microsoft.PowerShell.Commands.Internal.Format对我从 eg 返回的.* 对象数组做太多事情Format-Wide,但至少它包含输出,它不会以流氓方式出现在我的屏幕上,我可以在随时将数组传递给另一个格式化程序或输出程序。

Kei*_*ill 5

这是一个简单的函数,用于格式化列专业。您可以在 PowerShell 脚本中完成这一切:

function Format-WideColMajor {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        [AllowNull()]
        [AllowEmptyString()]
        [PSObject]
        $InputObject,

        [Parameter()]
        $Property
    )

    begin {
        $list = new-object System.Collections.Generic.List[PSObject]
    }

    process {
        $list.Add($InputObject)
    }

    end {
        if ($Property) {
            $output = $list | Foreach {"$($_.$Property)"}
        }
        else {
            $output = $list | Foreach {"$_"}
        }

        $conWidth = $Host.UI.RawUI.BufferSize.Width - 1
        $maxLen = ($output | Measure-Object -Property Length -Maximum).Maximum

        $colWidth = $maxLen + 1

        $numCols = [Math]::Floor($conWidth / $colWidth)
        $numRows = [Math]::Ceiling($output.Count / $numCols)

        for ($i=0; $i -lt $numRows; $i++) {
            $line = ""
            for ($j = 0; $j -lt $numCols; $j++) {
                $item = $output[$i + ($j * $numRows)]
                $line += "$item$(' ' * ($colWidth - $item.Length))"
            }
            $line
        }
    }
}
Run Code Online (Sandbox Code Playgroud)