使用format-wide格式的Powershell彩色目录列表不正确

5

我从http://tasteofpowershell.blogspot.com/2009/02/get-childitem-dir-results-color-coded.html获取了这个彩色dir脚本:

function ls {
  $regex_opts = ([System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [System.Text.RegularExpressions.RegexOptions]::Compiled)

  $fore = $Host.UI.RawUI.ForegroundColor
  $compressed = New-Object System.Text.RegularExpressions.Regex('\.(zip|tar|gz|rar)$', $regex_opts)
  $executable = New-Object System.Text.RegularExpressions.Regex('\.(exe|bat|cmd|ps1|psm1|vbs|rb|reg|dll|o|lib)$', $regex_opts)
  $executable = New-Object System.Text.RegularExpressions.Regex('\.(exe|bat|cmd|ps1|psm1|vbs|rb|reg|dll|o|lib)$', $regex_opts)
  $source = New-Object System.Text.RegularExpressions.Regex('\.(py|pl|cs|rb|h|cpp)$', $regex_opts)
  $text = New-Object System.Text.RegularExpressions.Regex('\.(txt|cfg|conf|ini|csv|log|xml)$', $regex_opts)

  Invoke-Expression ("Get-ChildItem $args") |
    %{
      if ($_.GetType().Name -eq 'DirectoryInfo') {
        $Host.UI.RawUI.ForegroundColor = 'DarkCyan'
        $_
        $Host.UI.RawUI.ForegroundColor = $fore
      } elseif ($compressed.IsMatch($_.Name)) {
        $Host.UI.RawUI.ForegroundColor = 'Yellow'
        $_
        $Host.UI.RawUI.ForegroundColor = $fore
      } elseif ($executable.IsMatch($_.Name)) {
        $Host.UI.RawUI.ForegroundColor = 'Red'
        $_
        $Host.UI.RawUI.ForegroundColor = $fore
      } elseif ($text.IsMatch($_.Name)) {
        $Host.UI.RawUI.ForegroundColor = 'Green'
        $_
        $Host.UI.RawUI.ForegroundColor = $fore
      } elseif ($source.IsMatch($_.Name)) {
        $Host.UI.RawUI.ForegroundColor = 'Cyan'
        $_
        $Host.UI.RawUI.ForegroundColor = $fore
      } else {
        $_
      }
    }
}

它的表现很好,但是大多数情况下,我只需要以宽格式显示文件名。因此,在调用invoke-expression之后,我添加了以下内容:

  Invoke-Expression ("Get-ChildItem $args") |
    %{
      if ($_.GetType().Name -eq 'DirectoryInfo') {
  :
  :
  :
        $_
      }
    } | format-wide -property Name
}

现在我有一个bug。只有第二列的颜色是正确的;每一列的第一个项目都会采用第二列项目的颜色。例如,如果我有:
> ls

Directory     Program.exe

即使Directory应该是DarkCyan,但是Directory和Program.exe都会变成红色。我该如何更正呢?


这是一个非常酷的脚本 :D - 我尝试使用powershell_ise.exe运行脚本。它在执行时着色输出(我设置了断点),但当它完成执行时,颜色不会保留。你知道为什么吗?我正在使用PowerShell 2.0(Windows 7)。你会如何从PowerShell中调用此脚本?假设我在桌面文件夹中保存了一个名为color.ps1的文件。然后我打开PowserShell,导航到该文件夹并键入.\color.ps1。什么也没发生。我错过了什么使这个脚本能够在PowerShell中运行? - Leniel Maccaferri
1
我不是专家,但我认为它只是定义了一个名为ls的函数。运行脚本后,您实际上必须通过ls运行该函数。您可能需要使用. .\color.ps1命令来源化color.ps1文件。 - Nathan Shively-Sanders
在加载color.ps1之后,我调用了ls函数,但输出仍然没有颜色。 - Leniel Maccaferri
1
确保您正在点操作文件 . .\color.ps1,然后执行 Get-ChildItemColor 命令,您应该能够看到带有颜色输出的结果。 - Keith Hill
感谢Nathan和Keith。现在我有了彩色输出。这个东西真的很酷。我之前只使用了.\color.ps1。当我使用. .\color.ps1时,它就起作用了。 - Leniel Maccaferri
2个回答

3

不要在显示文本时来回调整主机的前景/背景颜色,为什么不使用Write-Host呢?它可以让您更好地控制显示的文本(您可以控制何时输出换行符),例如:

$_ | Out-String -stream | Write-Host -Fore Red

如果你需要进行广泛的列出操作,除非你想更新DirectoryInfo / FileInfo类型的格式数据XML,否则你需要自己处理列的格式。如果不想这样做,那么可以逐个输出每个名称,并使用所需的颜色进行填充。在最后一列上,将- NoNewLine参数设置为$false:

$width =  $host.UI.RawUI.WindowSize.Width
$cols = 3   
ls | % {$i=0; $pad = [int]($width/$cols) - 1} `
       {$nnl = ++$i % $cols -ne 0; `
        Write-Host ("{0,-$pad}" -f $_) -Fore Green -NoNewLine:$nnl}

这很好用,除非$pad不是整数(80/3-1不是)。我编辑了你的示例以包括一个int转换。 - Nathan Shively-Sanders
要充分发挥其作用,您还应找到每个名称的最大长度,然后确定可以显示多少列,而不是将其硬编码为3。 :-) - Keith Hill
请问您能告诉我应该怎么做,让这个脚本可以在 PowerShell 中给我的输出着色吗?请看我在问题中的评论。 - Leniel Maccaferri
我尝试了你说的关于write-host的更改,但是现在每个项目都被打印成一个新的ls,即:一行路径,然后另一行标题,最后才是我真正想要的那一行。你如何正确应用这些更改? - mjsr
这样做只有一个问题 - 使用write-host 输出的结果会被转换为字符串,并且仅以文本形式输出。而标准的get-childitem则会输出一个对象,该对象对于管道等操作更有用。 - Fopedush

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接