Skip to content

Instantly share code, notes, and snippets.

@jdhitsolutions
Last active December 3, 2024 11:30
Show Gist options
  • Save jdhitsolutions/841fcd6f0318f9f51d2e05873ba658a4 to your computer and use it in GitHub Desktop.
Save jdhitsolutions/841fcd6f0318f9f51d2e05873ba658a4 to your computer and use it in GitHub Desktop.
A PowerShell command to trim the command history file used by PSReadline
#requires -version 5.0
#requires -module PSReadline
Function Optimize-PSReadLineHistory {
<#
.SYNOPSIS
Optimize the PSReadline history file
.DESCRIPTION
The PSReadline module can maintain a persistent command-line history. However, there are no provisions for managing the file. When the file gets very large, performance starting PowerShell can be affected. This command will trim the history file to a specified length as well as removing any duplicate entries.
.PARAMETER MaximumLineCount
Set the maximum number of lines to store in the history file.
.PARAMETER Passthru
By default this command does not write anything to the pipeline. Use -Passthru to get the updated history file.
.EXAMPLE
PS C:\> Optimize-PSReadelineHistory
Trim the PSReadlineHistory file to default maximum number of lines.
.EXAMPLE
PS C:\> Optimize-PSReadelineHistory -maximumlinecount 500 -passthru
Directory: C:\Users\Jeff\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/2/2017 8:21 AM 1171 ConsoleHost_history.txt
Trim the PSReadlineHistory file to 500 lines and display the file listing.
.INPUTS
None
.OUTPUTS
None
.NOTES
version 1.0
Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/
.LINK
Get-PSReadlineOption
.LINK
Set-PSReadlineOption
#>
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(ValueFromPipeline)]
[int32]$MaximumLineCount = $MaximumHistoryCount,
[switch]$Passthru
)
Begin {
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
$History = (Get-PSReadlineOption).HistorySavePath
} #begin
Process {
if (Test-Path -path $History) {
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Measuring $history"
$myHistory = Get-Content -Path $History
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found $($myHistory.count) lines of history"
$count = $myHistory.count - $MaximumLineCount
if ($count -gt 0) {
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Trimming $count lines to meet max of $MaximumLineCount lines"
$myHistory | Select-Object -skip $count -Unique | Set-Content -Path $History
}
}
else {
Write-Warning "Failed to find $history"
}
} #process
End {
If ($Passthru) {
Get-Item -Path $History
}
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
} #end
} #close Name
@Nightblade
Copy link

Hi Jeff!

This script is missing the .ps1 filename extension.

Also, I think it would be better if the script de-duplicated the file and re-checked the line count before hard-trimming it. I'm a bit of a PowerShell noob, but I had a go at this myself: https://gist.github.com/Nightblade/0b8a9cc73550964de348902548bdbbb9

I just had another thought, it might be nice to filter-out short lines, such as cd, cd .. etc. And/or allow a list of commands to exclude?

Regards,
Nighty

@jdhitsolutions
Copy link
Author

I guess I assumed people would know it is a .ps1 file. I don't worry about deduplication because I have the PSReadlineOption HistoryNoDuplicates already set to True. I like the idea of deleting location change commands.

@Nightblade
Copy link

Nightblade commented Dec 3, 2024

Hi Jeff,

I only mentioned the missing filename extension because the syntax highlighting wasn't working (here).

edit: I too have customized my PSReadlineOptions, but I thought removing duplicates might be useful for others.

Regards,
Nighty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment