How to normalize a path in PowerShell?
I have two paths:
fred\frog
and
..\frag
I can join them together in PowerShell like this:
join-path 'fred\frog' '..\frag'
That gives me this:
fred\frog\..\frag
But I don't want that. I want a normalized path without the double dots, like this:
fred\frag
How can I get that?
You can expand ..\frag to its full path with resolve-path:
PS > resolve-path ..\frag
Try to normalize the path using the combine() method:
[io.path]::Combine("fred\frog",(resolve-path ..\frag).path)
You can use a combination of $pwd
, Join-Path
and [System.IO.Path]::GetFullPath
to get a fully qualified expanded path.
Since cd
(Set-Location
) doesn't change the process current working directory, simply passing a relative file name to a .NET API that doesn't understand PowerShell context, can have unintended side-effects, such as resolving to a path based off the initial working directory (not your current location).
What you do is you first qualify your path:
Join-Path (Join-Path $pwd fred\frog) '..\frag'
This yields (given my current location):
C:\WINDOWS\system32\fred\frog\..\frag
With an absolute base, it is now safe to call the .NET API GetFullPath
:
[System.IO.Path]::GetFullPath((Join-Path (Join-Path $pwd fred\frog) '..\frag'))
Which gives you the fully qualified path, with the ..
correctly resolved:
C:\WINDOWS\system32\fred\frag
It's not complicated either, personally, I disdain the solutions that depend on external scripts for this, it's simple problem solved rather aptly by Join-Path
and $pwd
(GetFullPath
is just to make it pretty). If you only want to keep only the relative part, you just add .Substring($pwd.Path.Trim('\').Length + 1)
and voila!
fred\frag
UPDATE
Thanks to @Dangph for pointing out the C:\
edge case.