Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

PowerShell for the People: Making the shell work for you

Posted on September 2, 2014

021913_2047_WordTest1.png Once you have some basic PowerShell experience I think you will begin looking for all sorts of ways to use PowerShell. Although one of the biggest obstacles for many IT Pros is the thought of having to type everything. Certainly, PowerShell has a number of features to mitigate this, often misperceived, burden such as tab completion and aliases. It is the latter that I want to discuss today.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

An alias is simply an short command name alternative. Instead of typing Get-Process you can type ps. Even I can't screw that up. Using aliases at the command prompt is a great way to speed up your work and cut down on typos. While I wouldn't type this in a script:

gsv | ? status -eq running

At a prompt, it is quick and I get the desired results. However, you can't create an alias for a command and its parameters. For example, I love the -First and -Last parameters with Select-Object. But I can't create an alias equivalent to Select-Object -last 10. What you can do however, is create your own wrapper around a command and put an alias to that. Here is a function I wrote for Select-Object -Last X.

#requires -version 3.0 

Function Select-Last {

<#
.Synopsis
Select last X number of objects
.Description
This command takes pipelined input and selects the last specified number of objects which are then written to the pipeline.

There is a trade off of convenience for performance. For a very large number processed objects, use Select-Object directly
.Example
PS C:\> dir c:\scripts\*.ps1  | sort lastwritetime | last 5
.Notes
Last Updated: 8/25/2014
Version     : 0.9

.Link
Select-Object
#>

[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory,HelpMessage="How many objects do you want to get?")]
[ValidateScript({$_ -gt 0})]
[int]$Last,
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[object]$InputObject
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
    Write-Verbose -Message "Selecting last $Last objects"

    #initialize an array to hold all incoming objects
    $data=@()
    #initialize a counter
    $total=0
    #track when the command started in order to calculate how long the command took to complete.
    $start=Get-Date
} #begin

Process {
    $total++
    if ($total -le $Last) {
        #add each piped object to temporary array
        $data+=$InputObject
    }
    else {
      #move all items in the array up one
      $data = $data[1..$Last]
      #add the new item
      $data+=$InputObject
    }
} #process

End {
    #write the results
    $data
    $end = Get-Date
    Write-Verbose -Message "Processed $total items in $($end-$start)"
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
} #end
}

Set-Alias -Name Last -Value Select-Last

You'll notice that the last part of my code snippet is defining an alias called Last that references this function. But now I have something quick and easy to use at a PowerShell prompt.

dir c:\work\*.txt | sort lastwritetime | last 5

You'll have to figure out the best way to wrap the cmdlet. In this case, I am taking each piped in object and adding it to an array, only keeping the specified number of items. As each item is added, the other items are moved "up" in the array.

Be aware that there may be a trade-off between convenience and performance. This command using my alias and custom function:

Measure-command {1..5000 | last 3}

took 237ms. Whereas the Select-Object approach:

Measure-command {1..5000 | select -Last 3}

Only took 49ms. But I bet you might be willing to accept that tradeoff to save some typing. Of course, if there is a Last command there should be a First command.

Function Select-First {
<#
.Synopsis
Select first X number of objects
.Description
This command takes pipelined input and selects the first specified number of objects which are then written to the pipeline.
.Example
PS C:\> get-process | sort WS -descending | first 5
.Notes
Last Updated: 8/25/2014
Version     : 0.9

.Link
Select-Object
#>
[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory,HelpMessage="How many objects do you want to get?")]
[ValidateScript({$_ -gt 0})]
[int]$First,
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[object]$InputObject
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
    Write-Verbose -Message "Selecting first $First objects"
    #track when the command started in order to calculate how long the command took to complete.
    $start=Get-Date
    #initialize a counter
    $i=0
} #begin

Process {
    #add each piped object to temporary array
    $i++
   
    if ($i -le $First) {    
        $InputObject
    }
    else {
        #we're done here
        Write-Verbose "Limit reached"
        $end = Get-Date
        Write-Verbose -Message "Processed $($data.count) items in $($end-$start)"
        Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
        #bail out
        break
    }
} #process

End {
    #not used    
} #end
}

Set-Alias -Name First -Value Select-First

Performance-wise this is easier because all I have to do is count piped in objects and bail out once I reach the limit.

ps | sort ws -des | first 3

In this example I'm not only taking advantage of aliases, but also positional parameters and only having to type enough the of the parameter name so PowerShell knows what I want.

So there are ways to make PowerShell more keyboard friendly, although it might take a little work on your part. Next time we'll look at another alternative.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d