Reputation: 417
How to convert relative path to absolute path in PowerShell?
$path1 = C:/1/2/3/
$parth2 = ../../base/
=====
$result = C:/1/base/
Upvotes: 14
Views: 15132
Reputation: 455
I had to write a script where i wanted to provide default parameters for folder and file locations but since the user could overwrite them AND launch the script form any directory, i needed to properly handle this in a way it was as userfriendly as possible (e.g. using autocomplete of the ps-console provides for file paths)
I thought i'd share this here as I also struggled to properly handle relative paths (and wasted way too much time with .NET-Objects, trying to solve this)
as @Artem Yukhimenko provided the curcual cmdlet resolve-path
. I want to give the credits to him.
param (
[string] $SubFolderOne = "./SubfolderOne/",
[string] $ConfigFile = "./config.json",
[string] $SiblingFolder = "../SiblingFolder/"
)
function ResolveDefaultParameters {
# If the script has been run from a different directory and the path variables have been omitted, the default values would point to the wrong location.
# This function resolves the path to the script's directory if the path has been omitted.
param (
[string] $Path,
[string] $VarName
)
try {
# this will succeed if the path is already correct
$Path = $Path | Resolve-Path -ErrorAction Stop
}
catch {
try {
# This will fix the path so the default parameter value will join with the script's directory.
# If the parameter has been provided with a wrong path, the error will stop the script.
$Path = Join-Path $PSScriptRoot $Path | Resolve-Path -ErrorAction Stop
}
catch {
# had to manually throw the error, because the error from the `Resolve-Path` cmdlet would be missleading.
throw "Can't resolve path for `$$VarName`: '$Path'"
}
}
return $Path
}
$SubFolderOne = ResolveDefaultParameters -Path $SubFolderOne -VarName "SubFolderOne"
$ConfigFile = ResolveDefaultParameters -Path $ConfigFile -VarName "ConfigFile"
$SiblingFolder = ResolveDefaultParameters -Path $SiblingFolder -VarName "SiblingFolder"
# after handling the passed path parameters, we can set the script's location as the current location so we can access other files with known location more easily
$origLocation = Get-Location
Set-Location $PSScriptRoot
try {
# do the work here
Write-Host "SubFolderOne: $SubFolderOne"
Write-Host "ConfigFile: $ConfigFile"
Write-Host "SiblingFolder: $SiblingFolder"
#exeecute an a related script
.\Subroutines\RelatedScript.ps1
}
catch {
throw $_.Exception.Message
}
finally {
# return to original location
Set-Location $origLocation
}
Upvotes: 0
Reputation: 6294
Using the built-in .NET API - System.IO.Path.GetRelativePath:
[System.IO.Path]::GetFullPath($BasePath, $RelativePath)
# OR relative to current dir when ($BasePath -eq $PWD):
[System.IO.Path]::GetFullPath($RelativePath)
Upvotes: 1
Reputation: 7057
If your path is not existent yet, most of the above will blow up on you.
Either of the following will work even if the path doesn't exist yet:
[IO.Path]::GetFullPath(".\abc")
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(".\abc.txt")
Upvotes: 7
Reputation: 176
I think I get what you're looking for. But feel free to give a little more information if this isn't what you wanted.
$result = Get-Item $path2 | Select-Object PSPath -ExpandProperty PSPath
$result.Substring(38)
This should give you what you an absolute path. It strips out "Microsoft.Powershell.Core\Filesystem::" Which will be different if you're using Powershell 5 or earlier. But play with the Get-Item cmdlet to see how that displays if you want more detail.
Upvotes: 0