PowerShell has the Split-Path cmdlet that provides the leaf and parent of a path. But what if you’re splitting paths and need one or paths at a higher level.
Consider the path
PS> $path = 'C:\Scripts\HyperV\Admin\Optimize-VMDisks.ps1'
Its just an arbitrary path from my test machine.
Using Split-Path you can get the parent (by default) or the leaf path
PS> Split-Path -Path $path C:\Scripts\HyperV\Admin PS> Split-Path -Path $path -Parent C:\Scripts\HyperV\Admin PS> Split-Path -Path $path -Leaf Optimize-VMDisks.ps1
But what if you want the grandfather path. That starts to get ugly just using Split-Path.
PS> Split-Path -Path (Split-Path -Path $path -Parent) C:\Scripts\HyperV
The code gets uglier and uglier as you progress up the path
I decided I needed an object whose properties gave me a consistent view of the path hierarchy – the parent path was always level 1; the grandfather was always level 2 etc. Something like this
Level00 : C:\Scripts\HyperV\Admin\Optimize-VMDisks.ps1 Level01 : C:\Scripts\HyperV\Admin Level02 : C:\Scripts\HyperV Level03 : C:\Scripts Level04 : C:\
My solution was to create this function
function split-multipath { [CmdletBinding()] param ( [string]$path ) if (-not (Test-Path -Path $path -IsValid)) { throw "Invalid path: $path" } $outpaths = [ordered]@{ Level00 = $path } $l = 1 $path = Split-Path -Path $path -Parent while ($path -ne ''){ $level = "Level{0:00}" -f $l $outpaths += @{ $level = $path } $l++ $path = Split-Path -Path $path -Parent } New-Object -TypeName PSobject -Property $outpaths }
The split-multipath function takes a string as a parameter. That string is tested to determine if its a valid path – that could be moved to a ValidateScript test on the parameter.
The output is created from an ordered hash table. The Level00 property is set to the full path as input.
Set the counter and split the path to get the parent.
Use a while loop to add the current path into the hash table – create the property name with the string format operator –f.
Increment the counter and split the path – again taking the parent.
The while loop runs while the path has data. If you try to split when the path just contains the drive you get an empty string
PS> (Split-Path -Path c:\ -Parent) -eq '' True
The data is output as an object so you can access a particular level. For instance if you want the great-grandfather level – you use Level03
PS> $test.Level03 C:\Scripts
You can use the output object to create a new path based on the level of your choice
PS> Join-Path -Path $test.Level03 -ChildPath Test47 C:\Scripts\Test47