Archives For Programming


I still continue to fiddle about with PowerShell scripting on Windows 10. With PowerShell Core, PowerShell is also available for Linux and macOS. With that kind of cross-platform availability I’ve been trying to write code that works across Windows 10 Desktop as well as the Core implementations. This post is about a colored directory lister written in PowerShell that does that.

If you’re a Linux user, then you’re probably used to the colorization abilities of Gnu ls. I wanted that basic capability for Windows 10 and I wanted it to operate the same across all platforms. One feature I wanted was for this colored directory to show soft links, that is, identify a soft link and show what it pointed to. I managed to get that to work. The code follows.

function Get-ColoredDir {
    $regex_opts =
        ([System.Text.RegularExpressions.RegexOptions]::IgnoreCase `
          -bor [System.Text.RegularExpressions.RegexOptions]::Compiled)
    # Save the foreground and background colors. We'll restore when finished.
    $fore = $Host.UI.RawUI.ForegroundColor
    $back = $Host.UI.RawUI.BackgroundColor
    # Create regular expressions for finding compressed, executable, and text files.
    # We'll use these distinctions for our coloration below.
    $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|py|pl|ps1|psm1|vbs|rb|reg|msi|sh)$', $regex_opts)
    $text_files =
        New-Object System.Text.RegularExpressions.Regex('\.(txt|cfg|conf|ini|csv|log|xml|html|java|c|cpp|cs)$', $regex_opts)

    Invoke-Expression ("Get-ChildItem $args -Force") | ForEach-Object {

        $timestamp =
            '{0,2}/{1,2}/{2:D4} {3:D2}:{4:D2}:{5:D2}' -f
                $_.LastWriteTime.Month,
                $_.LastWriteTime.Day,
                $_.LastWriteTime.Year,
                $_.LastWriteTime.Hour,
                $_.LastWriteTime.Minute,
                $_.LastWriteTime.Second;

        $foretext = '{0, -10} {1} {2, 10} ' -f $_.Mode, $timestamp, $_.Length

        # Look to see if any of the objects found is a soft link.
        # Microsoft's term for a soft link is ReparsePoint.
        # Note the use of -Force to pick up hidden files, or files that start
        # with a period (.)
        $linkedItem = ''
        if ($_.Attributes -match "ReparsePoint") {
            $linkedItem = Get-Item -Force $_ | select-object -expandproperty Target
        }

        if ($_.GetType().Name -eq 'DirectoryInfo') {
            $Host.UI.RawUI.ForegroundColor = 'Cyan'
            if ($_.Attributes -match "ReparsePoint") {
                $Host.UI.RawUI.ForegroundColor = 'Magenta'
            }
        }
        elseif ($compressed.IsMatch($_.Name)) {
            $Host.UI.RawUI.ForegroundColor = 'Yellow'
        }
        elseif ($executable.IsMatch($_.Name)) {
            $Host.UI.RawUI.ForegroundColor = 'Red'
        }
        elseif ($text_files.IsMatch($_.Name)) {
            $Host.UI.RawUI.ForegroundColor = 'White'
        }
        else {
            $Host.UI.RawUI.ForegroundColor = $fore
        }

        if ($linkedItem.length -gt 0) {
            '{0}{1} -> {2}' -f $foretext, $_.Name, $linkedItem
        } else {
            '{0}{1}' -f $foretext, $_.Name
        }

    }

    $Host.UI.RawUI.ForegroundColor = $fore
    $Host.UI.RawUI.BackgroundColor = $back
}

I wouldn’t call this particularly exciting PowerShell code. I’m quite certain that a real PowerShell scripting guru would come up with something far more elegant. But it works, and it has examples of how to extract information for directory objects in a PowerShell environment, especially when determining soft links and what they resolve to. I hope you find it useful.

If you’re interested in PowerShell Core, you can find it on GitHub here: https://github.com/PowerShell/PowerShell

powershell on macos

July 4, 2017

I wrote in an earlier post about easily installing multiple applications on macOS. One of those applications interestingly enough is Microsoft’s PowerShell. Microsoft has open sourced PowerShell and made it available on GitHub (https://github.com/PowerShell/PowerShell). From GitHub you can either grab the source and build it yourself, download and install a pre-built binary, or both. I chose to just grab the binary and run with it as I have enough projects to keep me occupied as it is. The current PSVersion is 6.0.0-beta, and it’s shown running on macOS 10.12.5.

I start PowerShell for Mac from the ITerm2 command line, and from there I can look about PowerShell all I want. While the shell appears feature complete as far as syntax is concerned, PowerShell for Mac is missing considerable core .Net functionality when compared to the versions that run on Windows. As one small example shows below, Get-PSProvider doesn’t show the provider for the registry, as there is no equivalent (at all) on macOS. While it’s nice to have the same shell running across multiple platforms, as bash does, PowerShell for Mac and Linux isn’t going to be nearly as useful as it is on Windows if you want full Windows functionality on another OS. Any PowerShell scripts that are developed to take heavy advantage of Windows OS functionality are going to fail pretty hard on both the Mac and Linux, just to give you fair warning.

By the way, two comments on PowerShell help:

  1. If you decide to update PowerShell’s help, then run PowerShell as sudo before running Update-Help, or the updates will fail.
  2. The graphical view of help (via -ShowWindow) isn’t implemented and won’t work.

One tool not provided by the PowerShell project is the PowerShell ISE (Integrated Scripting Environment). The ISE is bundled with every copy of Windows these days, and is a powerful way to write and debug PowerShell scripts of any complexity on Windows. For the Mac the next best tool to use is Visual Studio Code with the PowerShell v1.4.1 extension (see below). You get full syntax highlighting and support as well as a split screen with code at the top and a PowerShell prompt at the bottom. The only major feature missing in this setup is the help section that is displayed to the right (by default) in the native ISE.

PowerShell for Mac and Visual Studio Code for Mac are an interesting counterpoint to Windows Subsystem for Linux on Windows 10. For those folk who like to “swim” in the lower regions of coding and operating systems, we’re living in a golden era.