如何在PowerShell中将绝对路径转换为相对路径?

时间:2012-09-12 20:51:06

标签: powershell

我想将路径转换为PowerShell脚本中的相对路径。 如何使用PowerShell执行此操作?

例如:

Path to convert: c:\documents\mynicefiles\afile.txt
Reference path:  c:\documents
Result:          mynicefiles\afile.txt

Path to convert: c:\documents\myproject1\afile.txt
Reference path:  c:\documents\myproject2
Result:          ..\myproject1\afile.txt

6 个答案:

答案 0 :(得分:50)

我找到了内置的内容,Resolve-Path

Resolve-Path -Relative

返回相对于当前位置的路径。一个简单的用法:

$root = "C:\Users\Dave\"
$current = "C:\Users\Dave\Documents\"
$tmp = Get-Location
Set-Location $root
Resolve-Path -relative $current
Set-Location $tmp

答案 1 :(得分:2)

使用内置的System.IO.Path.GetRelativePath比接受的答案更简单:

[System.IO.Path]::GetRelativePath($relativeTo, $path)

答案 2 :(得分:0)

一种快速简便的方法是:

$current -replace [regex]::Escape($root), '.'

或者如果您想要从当前实际位置开始的相对路径

$path -replace [regex]::Escape((pwd).Path), '.'

这假定您的所有路径均有效。

答案 3 :(得分:0)

here是一个很好的答案,但它会更改当前目录(它会还原),但是如果您确实需要隔离该过程,则下面的代码示例可以提供帮助。只是在一个新的PowerShell实例中,它做同样的事情。

function Get-RelativePath($path, $relativeTo) {
    $powershell = (Get-Process -PID $PID | Get-Item)
    if ([string]::IsNullOrEmpty($powershell)) {
        $powershell = "powershell.exe"
    }

    & $powershell -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "& { Set-Location `"$relativeTo`"; Resolve-Path `"$path`" -Relative}"
}

这确实很慢,除非您绝对必须使用此版本,否则您应该使用其他版本。

答案 4 :(得分:0)

有时我有多个“根”,我想从中生成相对的文件路径。我发现Resolve-Path -Relative在这种情况下不可用。更改全局设置(当前位置)以生成相对文件路径似乎容易出错,并且(如果您正在编写并行代码)可能不是线程安全的。

以下内容应在Powershell和Powershell Core的早期或最新版本中起作用,即使在临时状态下也不会更改您的当前目录,并且与操作系统无关并且是线程安全的。

它没有解决OP中的第二个示例(根据需要插入..。)

function Get-RelativePath {
    param($path, $relativeTo)
    # strip trailing slash
    $relativeTo = Join-Path `
                      (Split-Path -Parent $relativeTo) `
                      (Split-Path -Leaf $relativeTo)
    $relPath = Split-Path -Leaf $path
    $path = Split-Path -Parent $path
    do {    
        $leaf = Split-Path -Leaf $path
        $relPath = Join-Path $leaf $relPath
        $path = Split-Path -Parent $path
    } until (($path -eq $relativeTo) -Or ($path.Length -eq 0))
    $relPath
}

一个例子:

PS> $configRoot = 'C:\Users\P799634t\code\RMP\v2\AWD'
PS> $queryPath = 'C:\Users\P799634t\code\RMP\v2\AWD\config_queries\LOAD_UNQ_QUEUE_QUERY2.sql'
PS> Write-Host (Get-RelativePath $queryPath $configRoot)
config_queries\LOAD_UNQ_QUEUE_QUERY2.sql

当一个文件路径不是另一文件路径的子路径时,它的行为合理:

PS> $root = 'C:\Users\P799634t\code\RMP\v2\AWD'
PS> $notRelated = 'E:\path\to\origami'
PS> Write-Host (Get-RelativePath $notRelated $root)
E:\path\to\origami

答案 5 :(得分:-3)

这是另一种方法

$pathToConvert1 = "c:\documents\mynicefiles\afile.txt"
$referencePath1 = "c:\documents"
$result1 = $pathToConvert1.Substring($referencePath1.Length + 1)
#$result1:  mynicefiles\afile.txt


$pathToConvert2 = "c:\documents\myproject1\afile.txt"
#$referencePath2 = "c:\documents\myproject2"
$result2 = "..\myproject" + [regex]::Replace($pathToConvert2 , ".*\d+", '')
#$result2:          ..\myproject\afile.txt

注意:在第二种情况下,没有使用ref路径。

相关问题