Coloured directory listings in PowerShell

By default, PowerShell outputs drab directory listings. Unfortunately, there’s no built in solution to turning on colour, but it is possible with a few steps.

  1. This StackOverflow post gets us most of the way there. Towards the bottom of the question is some code that enables colourised output. I’ve modified it to suit my purposes (see below). This code should be put in your profile (see $profile to find the location).
  2. As noted, the code depends on the New-CommandWrapper cmdlet from the Powershell Cookbook. In my PowerShell profile directory, I’ve created a Scripts directory as a sibling to the regular Modules directory and put the cmdlet there.
  3. Ensure New-CommandWrapper.ps1 is unblocked (right click, Properties, Unblock) and in your PATH. If using the Scripts directory, you can put $env:Path += ";$(Split-Path $profile)\Scripts" in your profile.
  4. Using Set-ExecutionPolicy, ensure your execution policy is set to RemoteSigned or Unrestricted.
  5. Start a new shell, type dir or ls and enjoy.

As mentioned, I’ve modified the code in the StackOverflow post to suit my needs:

  • Cyan instead of Magenta directories. Magenta hurt my eyes.
  • Ignoring colouring text files separately as yellow. I have a lot of text files using different extensions and colouring text files didn’t provide any benefit.
  • Removed Perl, Python and Ruby extensions from executables. I don’t use Perl or Python and I have more Ruby code as part of a Rails app than standalone scripts.
  • Adjusted column spacing.
  • Don’t output a length for directories. It doesn’t show in the screenshot, but it displayed a length of 1 for directories.
  • Add coloured file count along with total file size at bottom.
  • Override both dir and ls aliases.
  • Renamed functions according to PowerShell verb-noun conventions.

The code that goes in your profile is:

New-CommandWrapper Out-Default -Process {
  $regex_opts = ([System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
  $compressed = New-Object System.Text.RegularExpressions.Regex(
    '\.(zip|tar|gz|rar|jar|war)$', $regex_opts)
  $executable = New-Object System.Text.RegularExpressions.Regex(
    '\.(exe|bat|cmd|msi|ps1|psm1|vbs|reg)$', $regex_opts)

  if(($_ -is [System.IO.DirectoryInfo]) -or ($_ -is [System.IO.FileInfo]))
  {
    if(-not ($notfirst))
    {
      Write-Host "`n    Directory: " -noNewLine
      Write-Host "$(pwd)`n" -foregroundcolor "Cyan"
      Write-Host "Mode        Last Write Time       Length   Name"
      Write-Host "----        ---------------       ------   ----"
      $notfirst=$true
    }

    if ($_ -is [System.IO.DirectoryInfo])
    {
      Write-Host ("{0}   {1}                {2}" -f $_.mode, ([String]::Format("{0,10} {1,8}", $_.LastWriteTime.ToString("d"), $_.LastWriteTime.ToString("t"))), $_.name) -ForegroundColor "Cyan"
    }
    else
    {
      if ($compressed.IsMatch($_.Name))
      {
        $color = "DarkGreen"
      }
      elseif ($executable.IsMatch($_.Name))
      {
        $color =  "Red"
      }
      else
      {
        $color = "White"
      }
      Write-Host ("{0}   {1}   {2,10}   {3}" -f $_.mode, ([String]::Format("{0,10} {1,8}", $_.LastWriteTime.ToString("d"), $_.LastWriteTime.ToString("t"))), $_.length, $_.name) -ForegroundColor $color
    }

    $_ = $null
  }
} -end {
  Write-Host
}

function Get-DirSize
{
  param ($dir)
  $bytes = 0
  $count = 0

  Get-Childitem $dir | Foreach-Object {
    if ($_ -is [System.IO.FileInfo])
    {
      $bytes += $_.Length
      $count++
    }
  }

  Write-Host "`n    " -NoNewline

  if ($bytes -ge 1KB -and $bytes -lt 1MB)
  {
    Write-Host ("" + [Math]::Round(($bytes / 1KB), 2) + " KB") -ForegroundColor "White" -NoNewLine
  }
  elseif ($bytes -ge 1MB -and $bytes -lt 1GB)
  {
    Write-Host ("" + [Math]::Round(($bytes / 1MB), 2) + " MB") -ForegroundColor "White" -NoNewLine
  }
  elseif ($bytes -ge 1GB)
  {
    Write-Host ("" + [Math]::Round(($bytes / 1GB), 2) + " GB") -ForegroundColor "White" -NoNewLine
  }
  else
  {
    Write-Host ("" + $bytes + " bytes") -ForegroundColor "White" -NoNewLine
  }
  Write-Host " in " -NoNewline
  Write-Host $count -ForegroundColor "White" -NoNewline
  Write-Host " files"

}

function Get-DirWithSize
{
  param ($dir)
  Get-Childitem $dir
  Get-DirSize $dir
}

Remove-Item alias:dir
Remove-Item alias:ls
Set-Alias dir Get-DirWithSize
Set-Alias ls Get-DirWithSize

2 thoughts on “Coloured directory listings in PowerShell”

Leave a Reply