How to normalize a path in PowerShell?

path, powershell

Solution

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.

Problem

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?

Original source

Related problems