1

I am working on a build script using psake and I need to create an absolute path from the current working directory with an inputted path which could either be a relative or absolute path.

Suppose the current location is C:\MyProject\Build

$outputDirectory = Get-Location | Join-Path -ChildPath ".\output"

Gives C:\MyProject\Build\.\output, which isn't terrible, but I would like without the .\. I can solve that issue by using Path.GetFullPath.

The problem arises when I want to be able to provide absolute paths

$outputDirectory = Get-Location | Join-Path -ChildPath "\output"

Gives C:\MyProject\Build\output, where I need C:\output instead.

$outputDirectory = Get-Location | Join-Path -ChildPath "F:\output"

Gives C:\MyProject\Build\F:\output, where I need F:\output instead.

I tried using Resolve-Path, but this always complains about the path not existing.

I'm assuming Join-Path is not the cmdlet to use, but I have not been able find any resources on how to do what I want. Is there a simple one-line to accomplish what I need?

Matthew
  • 24,703
  • 9
  • 76
  • 110

2 Answers2

2

You could use GetFullPath(), but you would need to use a "hack" to make it use you current location as the current Directory(to resolve relative paths). Before using the fix, the .NET method's current directory is the working directory for the process, and not the location you have specified inside the PowerShell process. See Why don't .NET objects in PowerShell use the current directory?

#Hack to make .Net methods use the shells current directory instead of the working dir for the process
[System.Environment]::CurrentDirectory = (Get-Location)
".\output", "\output", "F:\output" | ForEach-Object {
    [System.IO.Path]::GetFullPath($_)
}

Output:

C:\Users\Frode\output
C:\output
F:\output

Something like this should work for you:

#Hack to make .Net methods use the shells current directory instead of the working dir for the process
[System.Environment]::CurrentDirectory = (Get-Location)

$outputDirectory = [System.IO.Path]::GetFullPath(".\output")
Community
  • 1
  • 1
Frode F.
  • 52,376
  • 9
  • 98
  • 114
2

I don't think there's a simple one-liner. But I assume you need the path created anyway, if it doesn't exist yet? So why not just test and create it?

cd C:\
$path = 'C:\Windows', 'C:\test1', '\Windows', '\test2', '.\Windows', '.\test3'

foreach ($p in $path) {
    if (Test-Path $p) {
        (Get-Item $p).FullName
    } else {
        (New-Item $p -ItemType Directory).FullName
    }
}