source

PowerShell에서 절대 경로를 상대 경로로 변환하는 방법은 무엇입니까?

nicesource 2023. 7. 28. 22:10
반응형

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

기본 제공되는 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

기본 제공 시스템 사용.IO.경로.GetRelativePath는 허용된 답변보다 간단합니다.

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

여기에 좋은 대답이 있지만 현재 디렉터리가 변경됩니다(복귀됩니다). 그러나 해당 프로세스를 분리해야 하는 경우 아래 코드 예제를 참조하면 도움이 될 수 있습니다.새로운 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}"
}

정말 느리긴 하지만, 꼭 이것을 사용해야 하는 경우가 아니라면 다른 버전을 사용해야 합니다.

때때로 상대 파일 경로를 생성하려는 "루트"가 여러 개 있습니다.찾았습니다Resolve-Path -Relative이런 상황에서는 사용할 수 없습니다.상대적인 파일 경로를 생성하기 위해 글로벌 설정, 현재 위치를 변경하는 것은 오류가 발생하기 쉽고 (병렬 코드를 작성하는 경우) 스레드 세이프가 아닐 수 있습니다.

다음은 Powershell 및 Powershell Core의 초기 또는 최신 버전에서 작동하며 현재 디렉터리를 일시적으로 변경하지 않으며 OS에 의존하지 않고 스레드 안전합니다.

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

빠르고 쉬운 방법은 다음과 같습니다.

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

또는 실제 현재 위치에서 상대 경로를 원하는 경우

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

이렇게 하면 모든 경로가 유효하다고 가정합니다.

다음은 대안적인 접근 방식입니다.

$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

참고: 두 번째 경우에는 참조 경로가 사용되지 않았습니다.

언급URL : https://stackoverflow.com/questions/12396025/how-to-convert-absolute-path-to-relative-path-in-powershell

반응형