Powershell

# (pound sign) to search the Powershell history

I spend a lot of time working at the Powershell console so it is common for me to type (or retype) the same command multiple times; of course I tend to not really retype the same command every time but rather use Get-History and related cmdlets to re-execute previous commands:

λ 10 carlo@CARLOCXPS 12:24:53 carlo >_ Get-History

  Id CommandLine
  -- -----------
   1 Invoke-Expression '. ''C:\Utility\cmder\vendor\conemu-maximus5\..\profile.ps1'''
   2 dir
   3 gl
   4 h
   5 gps
   6 Get-AzContext
   7 h
   8 gmo
   9 h

The quickest way to re-execute a previous command is to use Invoke-History followed by the Id from Get-History:

λ 11 carlo@CARLOCXPS 12:32:46 carlo >_ Invoke-History 8
gmo

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     1.5.2      Az.Accounts                         {Add-AzEnvironment, Clear-AzContext, Clear-AzDefault, Connect-AzAccount…}
Script     2.7.3      LSEFunctions                        {Convert-CertBase64DataToFile, Convert-CertificateToBase64String, ConvertFrom-Base64, ConvertFrom-HashtableToPsCustomObject…}
Manifest   6.1.0.0    Microsoft.PowerShell.Management     {Add-Content, Clear-Content, Clear-Item, Clear-ItemProperty…}
Manifest   6.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object…}
Script     1.1.7.0    PackageManagement                   {Find-Package, Find-PackageProvider, Get-Package, Get-PackageProvider…}
Script     1.6.0      PowerShellGet                       {Find-Command, Find-DscResource, Find-Module, Find-RoleCapability…}
Script     1.2        PSReadLine                          {Get-PSReadlineKeyHandler, Get-PSReadlineOption, Remove-PSReadlineKeyHandler, Set-PSReadlineKeyHandler…}

I like to use shortcuts (or aliases, as you can see from my history above 😊) so I would normally use h (Get-History) and r <id> (Invoke-History <id>). Sometimes I need to slightly modify the command before running it again, there’s an easy solution for that as well:

λ 12 carlo@CARLOCXPS 12:54:48 carlo >_ (h 8).CommandLine | clip

Simply copy the CommandLine value from Get-History to the clipboard, paste it to the console and change what’s needed

PSReadLine improves the history search capability, here’s a list of bound key handlers related to history management:

λ 16 carlo@CARLOCXPS 12:58:19 carlo >_ Get-PSReadlineKeyHandler -Bound | ? Function -Match history

Key       Function              Description
---       --------              -----------
UpArrow   PreviousHistory       Replace the input with the previous item in the history
DownArrow NextHistory           Replace the input with the next item in the history
Ctrl+r    ReverseSearchHistory  Search history backwards interactively
Ctrl+s    ForwardSearchHistory  Search history forward interactively
Alt+F7    ClearHistory          Remove all items from the command line history (not PowerShell history)
F8        HistorySearchBackward Search for the previous item in the history that starts with the current input - like PreviousHistory if the input is empty
Shift+F8  HistorySearchForward  Search for the next item in the history that starts with the current input - like NextHistory if the input is empty

For example, using Ctrl+R (search history backwards) I can type a part of a string (“keyhan” in this example) and PSReadLine shows the first matching command, I can either hit TAB to accept the command and run it, or use CTRL+R to cycle through other commands matching the same substring. CTRL+S searches the history forward. Notice the “KeyHan” substring different coloring in the screenshot below, that is the match string I was typing:

search psreadline istory
search psreadline istory

To proof that there is always something new to learn, by happy mistake the other day I typed the pound sign followed by TAB (# > TAB) and I noticed Powershell transformed the input into the last entry from Get-History; hitting TAB again showed the previous history entry and so on. Moreover, #<string> > TAB (pound sign followed by a string and TAB) cycles through history entry that match the string typed after #: in other words considering the history below, #mod > TAB would loop through Install-Module and find-module commands.

A couple more interesting points to close with: this behavior seems to closely resemble CTRL+R from PSReadLine but I can reproduce it without PSReadLine loaded in my console; also, despite my research I could not find this behavior documented so here it is,

λ 31 carlo@CARLOCXPS 18:27:29 carlo >_ h

  Id CommandLine
  -- -----------
   1 Invoke-Expression '. ''C:\Utility\cmder\vendor\conemu-maximus5\..\profile.ps1'''
   2 dir
   3 gl
   4 h
   5 gps
   6 Get-AzContext
   7 h
   8 gmo
   9 h
  10 Get-History
  11 gmo
  12 (h 8).CommandLine | clip
  13 Get-PSReadlineKeyHandler -Bound
  14 Get-PSReadlineKeyHandler -Unbound
  15 Get-PSReadlineKeyHandler
  16 Get-PSReadlineKeyHandler -Bound | ? Function -Match history
  17 gmo PSReadLine
  18 find-module psreadline
  19 find-module psreadline -AllowPrerelease
  20 find-module psreadline -AllowPrerelease | Install-Module -Scope CurrentUser -Force -AllowClobber
  21 Install-Module psreadline -AllowPrerelease -Scope CurrentUser -Force
  22 gmo -list psreadline
  23 ipmo PSReadline -Version 2.0.0 -Force
  24 gmo
  25 h
  26 gcm #
  27 gcm $("#")
  28 gcm $("`#")
  29 gcm `#
  30 cls
powershell history #
powershell history #
λ 34 carlo@CARLOCXPS 18:45:23 carlo >_ gmo

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     1.5.2      Az.Accounts                         {Add-AzEnvironment, Clear-AzContext, Clear-AzDefault, Connect-AzAccount…}
Manifest   6.1.0.0    Microsoft.PowerShell.Management     {Add-Content, Clear-Content, Clear-Item, Clear-ItemProperty…}
Manifest   6.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object…}
Script     1.1.7.0    PackageManagement                   {Find-Package, Find-PackageProvider, Get-Package, Get-PackageProvider…}
Script     1.6.0      PowerShellGet                       {Find-Command, Find-DscResource, Find-Module, Find-RoleCapability…}

Your time is limited, so don’t waste it living someone else’s life. Don’t be trapped by dogma — which is living with the results of other people’s thinking. Don’t let the noise of others’ opinions drown out your own inner voice. And most important, have the courage to follow your heart and intuition. They somehow already know what you truly want to become. Everything else is secondary. – Steve Jobs

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.