19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

扱うパスが存在する場合

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

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

.ps1
$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

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

.ps1
$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を定義すると下記のようになんとかなる。

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

.ps1
$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

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

.ps1
$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 クラスを使っているだけ。

.ps1
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}"}
}

注意点

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

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

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

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

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

小ネタ

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

.ps1
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)

19
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?