Missed a dot

Missed a dot
Photo by Divazus Fabric Store / Unsplash

There is one operation I find myself doing a lot, and that the built in shorthand is a bit 'broken'.

The task

Working with objects means working with their properties / fields, and Select-Object -ExpandProperty <Property> is the operation I find using again and again and again.

There is a shorthand and that's the . (dot), but that is only really effective after an assignment took place.

Frustration by example:

To extract the full-path of a certain file, I might write the following:

Get-Item some-file-in-the-local-dir | Select-Object -ExpandProperty FullName
Exhibit A: The overly verbose solution

Which I find a bit too verbose, and the shorthand option would wither be:

$f = Get-Item some-file-in-the-local-dir
$f.FullName
Exhibit B1: The two statement solution

or

(Get-Item some-file-in-the-local-dir).FullName
Exhibit B2: The shortest solution

Why this bothers me

While Exhibit A is indeed too verbose, it has the best 'flow', I write the Get-Item statement, then I think about what I need to extract from it, and I continue to write the Select-Object statement.

Exhibit B (both B1 and B2) on the other hand, while substantially shorter, have a flow issue. While writing the code, I tend to write the Get-Item statement first, then move in front of it, add the assignment or the opening parenthesis, and then jump back to specify the property name.

There must be a better way

So, I've been thinking... How come there isn't a 'cleaner' shorthand for this?

Why not use % (the shorthand for ForEach-Object)?

That can work: ... | % { $_.<PropertyName> } this is actually better, but is there a way to it without the curly brackets?

This is what I came up with:

The solution is introducing to the environment a filter which is a very simple function like syntax that already has the necessary cmdlet pipeline pipework setup, and allows producing very concise code for a situation like this.

My code looks like this:

filter dot([string]$Parameter){ $_ | Select-Object -ExpandProperty $Parameter }
The filter

This results in the following syntax:

Get-Item some-file-in-the-local-dir | dot FullName
This is starting to look very good

So that's the | (pipe) character, followed by the filter-name dot a (space) and then the property-name, 5 characters long, and all of that without breaking the flow of writing a command line.

That's getting closer to Exhibit B2 but not quite, B2 is has the ( (opening parenthesis) at the beginning of the line, the . (dot) followed by ) (closing parenthesis). Technically 3 characters long, as long as I remembered to start with the ( before writing the statement.

So I also like to alias this filter by a single character name.

I really wished I was able to tie it to the . character, but I'm a realist, even if it was possible, it would probably introduce too many issues. Currently I'm trying out a few options.

I really wished there was a single keystroke option, not needing to use the Shift key, that would call for using a letter in the alphabet, as all other single-keystroke symbols on the keyboard, either have a specific meaning in PowerShell or just invalid.

The : (colon punctuation) seems to be a natural choice, as it is already used with static syntax [TypeName]::<member name>, and it is literally two dots. The underscore character _ seems like a good candidate as well.

Set-Alias ':' 'dot'

and now I can write the following command line:

Get-Item some-file-in-the-local-dir | : FullName

Not counting the optional white-space, that's 3 characters |, : and a (space), preserving the flow of scripting in the command line, concise yet very readable... which is the point I was trying to make in the first place (pun... very much intended).