Monday, December 19, 2016

The Power of PowerShell, Part 2

The Power of PowerShell, Part 2

In part one, I showed you some cool stuff you can do with PowerShell, covered the history of PowerShell, and explored in depth the capabilities of PowerShell as a strong scripting language that supports procedural, functional, and object-oriented programming. 

In part two, I'll discuss the interactive shell, the profile, and the prompt, and I'll compare PowerShell to Bash.

PowerShell: The Interactive Shell

PowerShell was designed from the get-go as an interactive shell for Windows sys admins and power users. It focuses on a small number of concepts, very consistent experience, and an object pipeline to chain and combine commands, filter them and format them. Its strong help system, which also adheres to a consistent format, is a pleasure to use.

Let's see some of that in action.

Getting Help

The comprehensive help system is accessible through Get-Help.

To get more detailed help and see examples, use the proper switches: -examples, -details, or -full.

If you're not sure what the command name is, just use keywords and PowerShell will show you all the available commands that contain this keyword. Let's see what cmdlets related to CSV are available:

I created a little pipeline where I limited the Get-Help call only to the category Cmdlet and then piped it to the "select" (alias for Select-Object) to get only the "name" property.

Working With Files and Directories

You can do pretty much everything you're used to: navigating to various directories, listing files and sub-directories, examining the content of files, creating directories and files, etc.

Working With Other Providers

With PowerShell, you can treat many things as file systems and navigate them using cd and check their contents using ls/dir. Here are some additional providers:

Let's check out the environment and see what Go-related environment variables are out there (on my machine):

Formatting

PowerShell encourages composing cmdlets with standard switches and creating pipelines. Formatting is an explicit concept where in the end of a pipeline you put a formatter. PowerShell by default examines the type of object or objects at the end of the pipe and applies a default formatter. But you can override it by specifying a formatter yourself. Formatters are just cmdlets. Here is the previous output displayed in list format:

The Profile

Power users that use the command line frequently have many tasks, pipelines, and favorite combinations of commands with default switches that they favor. The PowerShell profile is a PowerShell script file that is loaded and executed whenever you start a new session. You can put all your favorite goodies there, create aliases and functions, set environment variables, and pretty much everything else.

I like to create navigation aliases to deeply nested directories, activate Python virtual environments, and create shortcuts to external commands I run frequently, like git and docker.

For me, the profile is indispensable because PowerShell's very readable and consistent commands and switches are often too verbose, and the built-in aliases are often more trouble than help (I discuss this later). Here is a very partial snippet from my profile:

The Prompt 

PowerShell lets you customize your command prompt. You need to define a function called prompt(). You can see the built-in prompt function:

Here is a custom prompt function that displays the current time in addition to the current directory:

PS C:\Users\the_g> function prompt {"$(get-date) $(get-location) > "}

You can go wild, of course, and add colors and check various conditions like if you're in a particular git repository or if you're admin.

Aliases: The Dark Side

PowerShell got aliases wrong, in my opinion, on two separate fronts. First, the alias command only allows the renaming of commands. You can't add common flags or options to make commands more useful by aliasing them to themselves.

For example, if you want to search in text line by line, you can use the Select-String cmdlet:

That works, but many people would like to rename Select-String to grep. But grep is by default case-sensitive, while Select-String is not. No big deal—we'll just add the -CaseSensitive flag, as in:

Set-Alias -Name grep -Value "Select-String -CaseSensitive" 

Unfortunately, that doesn't work:

The value of an alias must be either a cmdlet, a function, a script, or a program. No flags or arguments are allowed. 

Now, you can do that very easily in PowerShell, but you'll have to use functions and not aliases. That pretty much constrains aliases to simple renaming, which can also be done by functions.

PowerShell vs. Bash

On the interactive shell side, PowerShell and Bash are pretty equal. Bash is more concise by default, but PowerShell's object pipeline makes complicated pipelines more manageable. ,

That said, you can probably accomplish anything with either one and if you're a power user then you'll have your own aliases, functions, and shortcuts for common tasks. On the scripting side, PowerShell goes far beyond Bash, and for system administration purposes it even beats Python, Ruby and friends. 

An important aspect is availability. Bash comes pre-installed with most *nix distributions (unless specifically stripped) including macOS. It can also be installed on Windows via cygwin, git-bash, or msys. PowerShell comes pre-installed on Windows and just recently became available on Mac and Linux.

Conclusion

If you use Windows as a development machine or if you manage Windows machines then PowerShell is an indispensable tool. It is truly a well thought out superset of the Unix shells, and it comes pre-installed. 

PowerShell is great software engineering at work. It evolved over a decade, and it kept innovating while maintaining its original conceptual integrity. The recent switch to open source and cross-platform signals that there is still a lot more to wait for.


No comments:

Post a Comment