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:
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
λ 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