Fun with History

In the Pixar film Cars, Mater demonstrates to Lightning McQueen how to drive backwards. Lightning is astounded. Mater explains, "Don’t need to know where I’m going as long as I know where I’ve been." Probably not the exact quote but the point is if you know what you’ve done or where you’ve been it makes it very easy to know where you’re going or what to do next. In PowerShell you can take advantage of the shell’s history objects to speed up what you want to do next.

Every PowerShell expression is stored as a history object which you can see by running Get-History.  Or I like to use the alias ‘h’. You’ll typically see the last 30 or so PowerShell expressions. The total size of your history buffer is controlled by the $MaximumHistoryCount variable which has a default value of 64.  In my PowerShell profile I increase it to 256.


To execute any past command use the Invoke-History cmdlet specifying the number of the history item you wish to re-execute. I prefer to use the alias ‘r’. The command will run immediately. There is no provision for bringing up the expression and editing it first. Although you can use -whatif to see what command would execute.

If you want to see earlier history items, you can either specify a specific history number

PS C:\> h 35

Id CommandLine
-- -----------
35 dir | remove-item -whatif -outvariable foofiles

PS C:\>

Or you can specify a range:

PS C:\> h (35..40)

Id CommandLine
-- -----------
35 dir | remove-item -whatif -outvariable foofiles
36 $foofiles
37 dir *.jdh
38 dir *.jdh | remove-item -whatif -outvariable foofiles
39 $foofiles
40 copy *.jdh *.abc

PS C:\>

To see the last X number of items use the -count parameter:

PS C:\> h -count 60

Finally, the history object itself has some additional properties you might find helpful. Here’s an example:

PS C:\> h 101 | select *

Id : 101
CommandLine : $f=gci "c:\users\jeff\documents" -recurse
ExecutionStatus : Completed
StartExecutionTime : 7/18/2008 12:42:54 PM
EndExecutionTime : 7/18/2008 12:42:57 PM

I can see that it took 3 seconds to run Get-ChildItem on my Documents folder. Or if I really want to get granular:

PS C:\> (h 101).EndExecutiontime - (h 101).StartExecutiontime

Days : 0
Hours : 0
Minutes : 0
Seconds : 3
Milliseconds : 285
Ticks : 32853285
TotalDays : 3.80246354166667E-05
TotalHours : 0.00091259125
TotalMinutes : 0.054755475
TotalSeconds : 3.2853285
TotalMilliseconds : 3285.3285

So the next time you’re wondering where you might be going in PowerShell, take a look at where you’ve been.