두 가지 경로가 있습니다.
fred\frog
과
..\frag
다음과 같이 PowerShell에서 함께 조인 할 수 있습니다.
join-path 'fred\frog' '..\frag'
그것은 나에게 이것을 준다 :
fred\frog\..\frag
그러나 나는 그것을 원하지 않는다. 다음과 같이 이중 점이없는 정규화 된 경로를 원합니다.
fred\frag
어떻게 얻을 수 있습니까?
두 가지 경로가 있습니다.
fred\frog
과
..\frag
다음과 같이 PowerShell에서 함께 조인 할 수 있습니다.
join-path 'fred\frog' '..\frag'
그것은 나에게 이것을 준다 :
fred\frog\..\frag
그러나 나는 그것을 원하지 않는다. 다음과 같이 이중 점이없는 정규화 된 경로를 원합니다.
fred\frag
어떻게 얻을 수 있습니까?
답변:
당신의 조합을 사용할 수 있습니다 pwd
, Join-Path
그리고 [System.IO.Path]::GetFullPath
완전한 확장 된 경로를 얻을 수 있습니다.
cd
( Set-Location
)는 프로세스의 현재 작업 디렉터리를 변경하지 않기 때문에 PowerShell 컨텍스트를 이해하지 못하는 .NET API에 상대 파일 이름을 전달하기 만하면 초기 작업을 기반으로하는 경로로 확인하는 것과 같은 의도하지 않은 부작용이 발생할 수 있습니다. 디렉터리 (현재 위치 아님).
당신이하는 일은 먼저 당신의 경로를 한정하는 것입니다.
Join-Path (Join-Path (pwd) fred\frog) '..\frag'
이것은 (내 현재 위치를 감안할 때) :
C:\WINDOWS\system32\fred\frog\..\frag
절대 기반을 사용하면 .NET API를 호출하는 것이 안전합니다 GetFullPath
.
[System.IO.Path]::GetFullPath((Join-Path (Join-Path (pwd) fred\frog) '..\frag'))
완전한 경로와 ..
제거 된 경로를 제공합니다 .
C:\WINDOWS\system32\fred\frag
그것은 개인적으로도 외부 스크립트에 의존하는 솔루션을 경멸합니다. Join-Path
그리고 pwd
( GetFullPath
그냥 예쁘게 만드는 것입니다)에 의해 적절하게 해결되는 간단한 문제 입니다. 상대 부분 만 유지하고 싶다면 그냥 추가 .Substring((pwd).Path.Trim('\').Length + 1)
하고 짜잔!
fred\frag
C:\
엣지 케이스 를 지적 해 주신 @Dangph에게 감사드립니다 .
cd c:\; "C:\fred\frag".Substring((pwd).Path.Length + 1)
. 큰 문제는 아닙니다. 알아 두어야 할 것입니다.
cd c:\; "C:\fred\frag".Substring((pwd).Path.Trim('\').Length + 1)
. 그래도 조금 길어지고 있습니다.
resolve-path를 사용하여 .. \ frag를 전체 경로로 확장 할 수 있습니다.
PS > resolve-path ..\frag
Combine () 메서드를 사용하여 경로를 정규화하십시오.
[io.path]::Combine("fred\frog",(resolve-path ..\frag).path)
C:\Windows
대 C:\Windows\
동일한 경로하지만 두 개의 서로 다른 결과
[io.path]::Combine
가 반전됩니다. 더 좋은 방법은 기본 Join-Path
PowerShell 명령을 사용하는 것입니다 . Join-Path (Resolve-Path ..\frag).Path 'fred\frog'
또한 최소한 PowerShell v3 Resolve-Path
부터는 -Relative
현재 폴더에 상대적인 경로로 확인하기위한 스위치를 지원 합니다. 언급 한 바와 같이, Resolve-Path
단지와는 달리, 기존의 경로와 함께 작동합니다 [IO.Path]::GetFullPath()
.
Path.GetFullPath 를 사용할 수도 있지만 (Dan R의 답변과 마찬가지로) 전체 경로를 제공합니다. 사용법은 다음과 같습니다.
[IO.Path]::GetFullPath( "fred\frog\..\frag" )
또는 더 흥미롭게
[IO.Path]::GetFullPath( (join-path "fred\frog" "..\frag") )
둘 다 다음을 생성합니다 (현재 디렉토리가 D : \라고 가정).
D:\fred\frag
이 메소드는 fred 또는 frag가 실제로 존재하는지 여부를 판별하지 않습니다.
[System.IO.Directory]::SetCurrentDirectory(((Get-Location -PSProvider FileSystem).ProviderPath))
[IO.Path]::GetFullPath()
PowerShell의 기본과 달리 Resolve-Path
존재하지 않는 경로에서도 작동합니다. 단점은 @JasonMArcher가 지적했듯이 .NET의 작업 폴더를 PS의 작업 폴더와 먼저 동기화해야한다는 것입니다.
Join-Path
존재하지 않는 드라이브를 참조하는 경우 예외가 발생합니다.
받아 들여진 대답은 큰 도움이되었지만 절대 경로도 제대로 '정규화'하지 못했습니다. 절대 경로와 상대 경로를 모두 정규화하는 내 파생 작업 아래에서 찾으십시오.
function Get-AbsolutePath ($Path)
{
# System.IO.Path.Combine has two properties making it necesarry here:
# 1) correctly deals with situations where $Path (the second term) is an absolute path
# 2) correctly deals with situations where $Path (the second term) is relative
# (join-path) commandlet does not have this first property
$Path = [System.IO.Path]::Combine( ((pwd).Path), ($Path) );
# this piece strips out any relative path modifiers like '..' and '.'
$Path = [System.IO.Path]::GetFullPath($Path);
return $Path;
}
[IO.Path]::GetFullPath()
일반 파일 이름에 대한 디렉토리를 올바르게 결정하지 않습니다.
PowerShell의 공급자 모델을 사용하면 PowerShell의 현재 경로가 Windows에서 프로세스의 작업 디렉터리라고 생각하는 것과 다를 수 있기 때문에 PowerShell이 아닌 경로 조작 기능 (예 : System.IO.Path의 기능)은 PowerShell에서 신뢰할 수 없습니다.
또한 이미 발견 한 것처럼 PowerShell의 Resolve-Path 및 Convert-Path cmdlet은 상대 경로 ( '..'s 포함)를 드라이브 한정 절대 경로로 변환하는 데 유용하지만 참조 된 경로가 존재하지 않으면 실패합니다.
다음의 매우 간단한 cmdlet은 존재하지 않는 경로에 대해 작동합니다. 'fred'또는 'frag'파일 또는 폴더를 찾을 수없는 경우에도 'fred \ frog \ .. \ frag'를 'd : \ fred \ frag'로 변환합니다 (현재 PowerShell 드라이브는 'd :'). .
function Get-AbsolutePath {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string[]]
$Path
)
process {
$Path | ForEach-Object {
$PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_)
}
}
}
Get-AbsolutePath q:\foo\bar\..\baz
유효한 경로인데도 실패합니다. 글쎄, 유효한 경로에 대한 정의에 따라. :-) FWIW, 심지어는 Test-Path <path> -IsValid
존재하지 않는 드라이브에 루트가있는 경로 에서 내장 오류가 발생합니다.
HKLM:\SOFTWARE
의 SOFTWARE
키를 참조하는 PowerShell의 유효한 경로입니다 . 그러나 그것이 유효한지 알아 내려면 레지스트리 경로에 대한 규칙이 무엇인지 파악해야합니다.
이 라이브러리는 좋습니다 : NDepend.Helpers.FileDirectoryPath .
편집 : 이것은 내가 생각 해낸 것입니다.
[Reflection.Assembly]::LoadFrom("path\to\NDepend.Helpers.FileDirectoryPath.dll") | out-null
Function NormalizePath ($path)
{
if (-not $path.StartsWith('.\')) # FilePathRelative requires relative paths to begin with '.'
{
$path = ".\$path"
}
if ($path -eq '.\.') # FilePathRelative can't deal with this case
{
$result = '.'
}
else
{
$relPath = New-Object NDepend.Helpers.FileDirectoryPath.FilePathRelative($path)
$result = $relPath.Path
}
if ($result.StartsWith('.\')) # remove '.\'.
{
$result = $result.SubString(2)
}
$result
}
다음과 같이 호출하십시오.
> NormalizePath "fred\frog\..\frag"
fred\frag
이 스 니펫에는 DLL 경로가 필요합니다. 현재 실행중인 스크립트가 포함 된 폴더를 찾는 데 사용할 수있는 트릭이 있지만 제 경우에는 사용할 수있는 환경 변수가 있으므로 방금 사용했습니다.
이것은 전체 경로를 제공합니다.
(gci 'fred\frog\..\frag').FullName
이것은 현재 디렉토리에 상대적인 경로를 제공합니다.
(gci 'fred\frog\..\frag').FullName.Replace((gl).Path + '\', '')
어떤 이유로 그들은 frag
파일이 아닌 directory
.
함수를 만듭니다. 이 기능은 시스템에 존재하지 않는 경로를 정규화하고 드라이브 문자를 추가하지 않습니다.
function RemoveDotsInPath {
[cmdletbinding()]
Param( [Parameter(Position=0, Mandatory=$true)] [string] $PathString = '' )
$newPath = $PathString -creplace '(?<grp>[^\n\\]+\\)+(?<-grp>\.\.\\)+(?(grp)(?!))', ''
return $newPath
}
전의:
$a = 'fooA\obj\BusinessLayer\..\..\bin\BusinessLayer\foo.txt'
RemoveDotsInPath $a
'fooA\bin\BusinessLayer\foo.txt'
RegEx에 도움을 주신 Oliver Schadlich에게 감사드립니다.
somepaththing\.\filename.txt
가 그 하나의 점 유지로
경로에 한정자 (드라이브 문자)가 포함 된 경우 Powershell에 대한 x0n의 대답 : 존재하지 않을 수있는 경로를 해결 하시겠습니까? 경로를 정상화합니다. 경로에 한정자가 포함되지 않은 경우에도 정규화되지만 현재 디렉터리에 상대적인 정규화 된 경로를 반환합니다. 이는 원하는 것이 아닐 수 있습니다.
$p = 'X:\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
X:\fred\frag
$p = '\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\fred\frag
$p = 'fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\Users\WileCau\fred\frag
여기서 주석의 편리한 부분은 상대 경로와 절대 경로를 통합하도록 결합되었습니다.
[System.IO.Directory]::SetCurrentDirectory($pwd)
[IO.Path]::GetFullPath($dapath)
일부 샘플 :
$fps = '.', 'file.txt', '.\file.txt', '..\file.txt', 'c:\somewhere\file.txt'
$fps | % { [IO.Path]::GetFullPath($_) }
산출:
C:\Users\thelonius\tests
C:\Users\thelonius\tests\file.txt
C:\Users\thelonius\tests\file.txt
C:\Users\thelonius\file.txt
c:\somewhere\file.txt