I have two paths:
fred\\frog
and
..\\frag
I can join them together in PowerShell like this:
Well, one way would be:
Join-Path 'fred\frog' '..\frag'.Replace('..', '')
Wait, maybe I misunderstand the question. In your example, is frag a subfolder of frog?
Create a function. This function will normalize a path that does not exists on your system as well as not add drives letters.
function RemoveDotsInPath {
[cmdletbinding()]
Param( [Parameter(Position=0, Mandatory=$true)] [string] $PathString = '' )
$newPath = $PathString -creplace '(?<grp>[^\n\\]+\\)+(?<-grp>\.\.\\)+(?(grp)(?!))', ''
return $newPath
}
Ex:
$a = 'fooA\obj\BusinessLayer\..\..\bin\BusinessLayer\foo.txt'
RemoveDotsInPath $a
'fooA\bin\BusinessLayer\foo.txt'
Thanks goes out to Oliver Schadlich for help in the RegEx.
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)
The accepted answer was a great help however it doesn't properly 'normalize' an absolute path too. Find below my derivative work which normalizes both absolute and relative paths.
function Get-AbsolutePath ($Path)
{
# System.IO.Path.Combine has two properties making it necesarry here:
# 1) correctly deals with situations where $Path (the second term) is an absolute path
# 2) correctly deals with situations where $Path (the second term) is relative
# (join-path) commandlet does not have this first property
$Path = [System.IO.Path]::Combine( ((pwd).Path), ($Path) );
# this piece strips out any relative path modifiers like '..' and '.'
$Path = [System.IO.Path]::GetFullPath($Path);
return $Path;
}
This gives the full path:
(gci 'fred\frog\..\frag').FullName
This gives the path relative to the current directory:
(gci 'fred\frog\..\frag').FullName.Replace((gl).Path + '\', '')
For some reason they only work if frag
is a file, not a directory
.
If the path includes a qualifier (drive letter) then x0n's answer to Powershell: resolve path that might not exist? will normalize the path. If the path doesn't include the qualifier, it will still be normalized but will return the fully qualified path relative to the current directory, which may not be what you want.
$p = 'X:\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
X:\fred\frag
$p = '\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\fred\frag
$p = 'fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\Users\WileCau\fred\frag