Home > Net >  Convert relative path into absolute string path
Convert relative path into absolute string path

Time:12-19

I need to store a relative path, as an absolute path in a file. I've tried quite a few things, including:

$path = (resolve-path -path "C:\Folder\..\Folder2").Path.ToString()

Add-content "d:\textfile.txt" $path

Which leaves an empy file. So I'm stumped.

CodePudding user response:

The simplest way to resolve a relative and/or non-normalized path (one with components such as .. and .) to a normalized full path, directly as a string, is to use the Convert-Path cmdlet:

Convert-Path -LiteralPath "C:\Folder\..\Folder2"

In the context of your command (note that Add-Content appends to a preexisting target file; to write the given content only, use Set-Content):

Add-Content "d:\textfile.txt" (Convert-Path -LiteralPath "C:\Folder\..\Folder2")

Note:

  • Unlike Resolve-Path, Convert-Path returns a file-system-native path, which is generally preferable.

    • This means that file-system paths that are based on PowerShell-only drives (created with New-PSDrive) are resolved to the underlying native file-system location, as understood by outside processes too. (E.g., if MyDrive: is mapped to C:\Projects, Convert-Path -LiteralPath MyDrive:\Foo returns C:\Projects\Foo)
  • Like Resolve-Path, Convert-Path requires that the item the path refers to exist - which is an unfortunate limitation, discussed in GitHub issue #2993.


If the input path refers to a nonexistent file or directory:

.NET offers the [System.IO.Path]::GetFullPath() method, which offers the same functionality also for nonexistent paths.

The challenge is that relative paths are resolved to .NET's current (working) directory, which usually differs from PowerShell's - see this answer for more information.

In PowerShell (Core) 7 , you can work around this problem by specifying the reference path (to resolve the relative path against) explicitly:

# Note: The 'System.' prefix in the type literal is optional.
[IO.Path]::GetFullPath("C:\Folder\..\Folder2", $PWD.ProviderPath)

The automatic $PWD variable refers to PowerShell's current location (directory). Note the use of .ProviderPath, which again ensures uses of a file-system-native path. For maximum robustness - to guard agains the case where the current PowerShell location isn't a file-system location - use (Get-Location -PSProvider FileSystem).ProviderPath.

In Windows PowerShell, where this method overload isn't available, a more cumbersome approach is needed, as suggested by Theo:

[IO.Path]::GetFullPath(
  [IO.Path]::Combine($PWD.ProviderPath, "C:\Folder\..\Folder2")
)
  • [IO.Path]::Combine() conditionally combines the first path given with the second one, if the latter is relative - otherwise, the latter is used as-is.

  • [IO.Path]::GetFullPath() then ensures normalization of the resulting full path (to resolve any . and .. components).

  • Related