Useful PowerShell

January 05, 2016

I joined my third Windows project as a consultant in May 2014. Over the past five years I’ve become more dependent on shell. While many folks seem content to mouse their way around Windows or jump to cygwin, I found PowerShell capable of doing just about everything I needed to. Here is my guide to Useful PowerShell.

The Basics

Everything in PowerShell follows the same ‘Verb-Noun’ convention. Many common commandlets are also aliased to their unix equivalents. For example, Get-ChildItem is aliased to ls. If you’re interested in the aliases of a known command, you can use Get-Alias.

# known command
Get-Alias -Definition Get-ChildItem

# all defined aliases
Get-Alias

The Get-Help commandlet is one of the most useful, especially if you prefer to learn by example.

Get-Help Get-ChildItem -Examples

Everything native to PowerShell can tab-complete, including parameters. The verbosity is not as bad as it seems. When it comes to reading scripts, it’s actually kind of nice to get that clarity. It’s also a surefire laugh for folks with unix shell backgrounds and a sense of humor. After all, who needs touch when you have New-Item -Type File?

The environment variable syntax is often confusing for new folks. We have access to all of .NET, so there are multiple ways to get this done, but the easiest way I’ve found is to just stick a $env: on the front.

# Add something to the PATH for the current session only
$env:PATH += ";c:\tools\bin"

# show all environment variables, note there is no '$' and the ':' is required
Get-ChildItem env:

# using familiar aliases
ls env:

The Profile

It’s easy to customize bash by popping open ~/.bashrc and proceeding to define functions, choose the folder to start in, set environment variables, or anything. PowerShell has the same thing going on, but it’s slightly more difficult to get going.

PowerShell’s profile is at a really long path in a folder that doesn’t exist by default. To create a brand new profile on your system, you’ll first need to create it.

New-Item -Path $Profile -Type File -Force

This is nice because none of the directories have to exist before the command is run. It reminds me of mkdir -p on unix, and indeed behaves exactly the same way for -Type Directory.

After you have the profile created, you can edit it with any text editor on your system.

notepad $Profile

Any valid PowerShell command will be executed when the shell loads. This is where I cd into my code directory and define a few useful functions.

Useful Commands

These are some things I used just about every day.

tail

Get-Content myfile.log -Wait

find

# Where is git installed?
$results = Get-ChildItem -Path C:\ -Filter git.exe -Recurse -ErrorAction SilentlyContinue
$git = $results | % { $_.Directory } | Select-Object -First 1

Note: appending -ErrorAction SilentlyContinue is not necessary, but often produces better output. PowerShell will fill the screen with red errors when searching folders the current user doesn’t have access to.

pbcopy

Useful for copying output from the command line. pbcopy is actually mac-specific, but similar tools exist for unix.

Get-Content '.\version.txt' | clip.exe

Previously Covered

Look Out!

Dot-separated properties do not work the same in PowerShell as cmd.exe. For example, if you had a deploy task whose default http.port could be overridden, you’d find that this worked great in cmd.exe and failed silently in PowerShell.

ant deploy -Dhttp.port=8888

This can be dangerous when it is not immediately obvious the value wasn’t taken. To get the same thing working in PowerShell, you’d need to quote the entire define.

ant deploy -D'http.port=8888'

Importantly this is only for dot-separated properties, which are very common in ant. If your project has properties defined with hyphens (http-port), camelCase (httpPort), or most any other way, it’ll work without quotes in both PowerShell and cmd.exe.

Wrapping Up

I had a good time picking up a new skill set while in Windows. I still prefer unix, but it’s nice to know many of the tools I’ve come to depend on have native Windows equivalents. We were able to script lots of tasks that were formerly drag-and-drop with a tool that just worked on every machine. This saved us a ton of time over the course of a year.


Profile picture

Written by @sghill, who works on build, automated change, and continuous integration systems.