Help us understand the problem. What is going on with this article?

Powershellで絶対パスと相対パスを相互変換したい

More than 3 years have passed since last update.

扱うパスが存在する場合

Test-Path$trueが返ってくるパスを扱う場合、Resolve-Pathで相互変換できる。

相対パスから絶対パスへの変換例

$root = "C:\foo\bar" # 基準となるパス
$rltv = "..\baz.txt" # 相対パス

Push-Location $root
    (Resolve-Path $rltv).Path      # => C:\foo\baz.txt (変換される)
    $root | Test-Path              # => True
    Resolve-Path $rltv | Test-Path # => True
Pop-Location

絶対パスから相対パスへの変換例

$root = "C:\foo\bar"     # 基準となるパス
$abs  = "C:\foo\baz.txt" # 絶対パス

Push-Location $root
    Resolve-Path $abs -Relative # => ..\baz.txt (変換される)
    $root | Test-Path           # => True
    $abs  | Test-Path           # => True
Pop-Location

扱うパスが存在しない場合

Push-LocationResolve-Pathは、存在しないパスを指定すると例外が発生するので別の方法が必要になる。
後述するConvert-LocalPathを定義すると下記のようになんとかなる。

相対パスから絶対パスへの変換例

$root = "X:\foo\bar\" # 基準となるパス
$rltv = "..\baz.txt"  # 相対パス

$rltv | Convert-LocalPath -Location $root             # => X:\foo\baz.txt (変換される)
$root | Test-Path                                     # => False
$rltv | Convert-LocalPath -Location $root | Test-Path # => False

絶対パスから相対パスへの変換例

$root = "X:\foo\bar\"    # 基準となるパス
$abs  = "X:\foo\baz.txt" # 絶対パス

$abs  | Convert-LocalPath -Location $root -Relative # => ..\baz.txt (変換される)
$root | Test-Path                                   # => False
$abs  | Test-Path                                   # => False

Convert-LocalPath

中身はURI クラスを使っているだけ。

filter Convert-LocalPath
{
    Param
    (
        [parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [string] $Path,

        [ValidateNotNullOrEmpty()]
        [uri] $Location = (Get-Location).Path,

        [switch] $Relative
    )

    if (-not $Relative) {return [uri]::new($Location, $Path).LocalPath}

    $localPath = $Location.MakeRelative($Path) -replace '/', '\'
    if ($localPath.StartsWith('.')) {$localPath} else {".\${localPath}"}
}

注意点

末尾に"\"がないとフォルダ扱いされません。

PS C:\> "..\baz.txt" | Convert-LocalPath -Location "X:\foo\bar"
X:\baz.txt

FunctionVariableなどのPSDriveは扱えません。

PS C:\> ".\NG" | Convert-LocalPath -Location "Function:"
./NG

PS C:\> ".\NG" | Convert-LocalPath -Location "Variable:"
./NG

小ネタ

動的型付けとオーバーロードの地獄感がすごい

PS C:\> [URI]::new("Z:\", "zzz").LocalPath
Z:\
PS C:\> [URI]::new("Z:\", [string]"zzz").LocalPath
Z:\zzz

PS C:\> [URI]::new

OverloadDefinitions
-------------------
uri new(string uriString)
uri new(string uriString, bool dontEscape)
uri new(uri baseUri, string relativeUri, bool dontEscape)
uri new(string uriString, System.UriKind uriKind)
uri new(uri baseUri, string relativeUri)
uri new(uri baseUri, uri relativeUri)

yumura_s
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away