Created
July 15, 2021 10:34
-
-
Save loilo/db7c4bb261bcb3baf711aacf68d835f9 to your computer and use it in GitHub Desktop.
Shorten a path in PowerShell Core 7+
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Shorten a path in PowerShell by omitting segments from the beginning. | |
# Parameter defaults are designed to be used in a prompt. | |
# Requires at least PowerShell Core 7. | |
function shorten-path { | |
<# | |
.SYNOPSIS | |
Shortens a path from the end. | |
.DESCRIPTION | |
Shortens a path by omitting segments from the beginning. Useful e.g. to shorten the CWD in prompt. | |
.EXAMPLE | |
PS> shorten-path 'C:\foo\bar\baz\qux' | |
foo\bar\baz\qux | |
.EXAMPLE | |
PS> shorten-path -Path 'C:\foo\bar\baz\qux' | |
foo\bar\baz\qux | |
.EXAMPLE | |
PS> 'C:\foo\bar\baz\qux' | shorten-path | |
foo\bar\baz\qux | |
.EXAMPLE | |
PS> shorten-path -MaxLength 5 'C:\foo\bar\baz\qux' | |
baz\qux | |
.EXAMPLE | |
PS> shorten-path -MaxLength 1 'C:\foo\bar\baz\qux' | |
qux | |
.EXAMPLE | |
PS> shorten-path -MaxSegments 3 'C:\foo\bar\baz\qux' | |
bar\baz\qux | |
.EXAMPLE | |
PS> shorten-path -MaxSegments 0 'C:\foo\bar\baz\qux' | |
C:\foo\bar\baz\qux | |
#> | |
[CmdletBinding(PositionalBinding = $false)] | |
param ( | |
[Parameter(ValueFromPipeline, Position = 0, HelpMessage = "The path to shorten.")] | |
[string] | |
$Path = (Get-Location), | |
[Parameter(HelpMessage = "Maximum number of path segments to keep, 0 to disable. Defaults to 4.")] | |
[int] | |
$MaxSegments = 4, | |
[Parameter(HelpMessage = "Maximum length of shortened path, 0 to disable. Defaults to 1/3 of the terminal width, minimum 30.")] | |
[int] | |
$MaxLength = [math]::Max( | |
[math]::Round($Host.UI.RawUI.WindowSize.Width) / 3, | |
30 | |
) | |
) | |
$array = @(); | |
# Fallback result is a single folder | |
$result = $Path | Split-Path -Leaf; | |
$max_i = ($MaxSegments -eq 0 ? [double]::PositiveInfinity : $MaxSegments); | |
for ($i = 0; $i -lt $max_i; $i++) { | |
# Get the path leaf for the current iteration | |
# (e.g. iterated leaf for $i = 1 of "C:\foo\bar" would be "foo") | |
$iterated_leaf = $Path; | |
for ($j = 0; $j -lt $i; $j++) { | |
$next_iterated_leaf = ($iterated_leaf | Split-Path); | |
# Bail out if file system root was reached early | |
if ($next_iterated_leaf.Length -eq 0) { | |
Write-Verbose "Done; root segment '$iterated_leaf' was reached." | |
return $result; | |
} | |
$iterated_leaf = $next_iterated_leaf; | |
} | |
$iterated_leaf = ($iterated_leaf | Split-Path -Leaf); | |
$array = $array + $iterated_leaf; | |
$reversed = $array[($array.Length - 1)..0]; | |
$next_result = (($reversed.Length -eq 1) ? | |
$reversed[0] : | |
(Join-Path @reversed)); | |
# Bail out if maximum path length was reached early | |
if (($MaxLength -gt 0) -And ($next_result.Length -gt $MaxLength)) { | |
if ($array.Length -eq 1) { | |
Write-Verbose "Done; initial segment '$($iterated_leaf)' already exceeds maximum length ($MaxLength)." | |
} | |
else { | |
Write-Verbose "Done; maximum length ($MaxLength) would be exceeded with additional segment '$($iterated_leaf)'." | |
} | |
return $result; | |
} | |
$result = $next_result; | |
} | |
Write-Verbose "Done; maximum number of segments ($MaxSegments) reached." | |
return $result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment