Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 704
dan-gph Avatar asked Jan 30 '09 14:01

dan-gph


People also ask

How do I get full path in PowerShell?

Use the Get-ChildItem cmdlet in PowerShell to get the full path of the file in the current directory. Get-ChildItem returns one or more items from the specified location and using the file FullName property, it gets the full path of the file.

How do I change the path in PowerShell?

You can also change directory in PowerShell to a specified path. To change directory, enter Set-Location followed by the Path parameter, then the full path you want to change directory to. If the new directory path has spaces, enclose the path in a double-quote (“”).

What is LiteralPath in PowerShell?

-LiteralPath. Specifies the path to be resolved. The value of the LiteralPath parameter is used exactly as typed. No characters are interpreted as wildcard characters. If the path includes escape characters, enclose it in single quotation marks ( ' ).


2 Answers

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) 
like image 173
Shay Levy Avatar answered Oct 09 '22 22:10

Shay Levy


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.

like image 35
John Leidegren Avatar answered Oct 09 '22 22:10

John Leidegren