PowerShell에서 경로를 정규화하는 방법은 무엇입니까?
두 가지 경로가 있습니다.
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에게 감사드립니다 .
resolve-path를 사용하여 .. \ frag를 전체 경로로 확장 할 수 있습니다.
PS > resolve-path ..\frag
Combine () 메서드를 사용하여 경로를 정규화하십시오.
[io.path]::Combine("fred\frog",(resolve-path ..\frag).path)
Path.GetFullPath 를 사용할 수도 있지만 (Dan R의 답변과 마찬가지로) 전체 경로를 제공합니다. 사용법은 다음과 같습니다.
[IO.Path]::GetFullPath( "fred\frog\..\frag" )
또는 더 흥미롭게
[IO.Path]::GetFullPath( (join-path "fred\frog" "..\frag") )
둘 다 다음을 생성합니다 (현재 디렉토리가 D : \라고 가정).
D:\fred\frag
이 메소드는 fred 또는 frag가 실제로 존재하는지 여부를 판별하지 않습니다.
받아 들여진 대답은 큰 도움이되었지만 절대 경로도 제대로 '정규화'하지 못했습니다. 절대 경로와 상대 경로를 모두 정규화하는 내 파생 작업 아래에서 찾으십시오.
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;
}
PowerShell의 공급자 모델을 사용하면 PowerShell의 현재 경로가 Windows에서 프로세스의 작업 디렉터리라고 생각하는 것과 다를 수 있기 때문에 PowerShell이 아닌 경로 조작 기능 (예 : System.IO.Path의 기능)은 PowerShell에서 신뢰할 수 없습니다.
Also, as you may have already discovered, PowerShell's Resolve-Path and Convert-Path cmdlets are useful for converting relative paths (those containing '..'s) to drive-qualified absolute paths but they fail if the path referenced does not exist.
The following very simple cmdlet should work for non-existant paths. It will convert 'fred\frog\..\frag' to 'd:\fred\frag' even if a 'fred' or 'frag' file or folder cannot be found (and the current PowerShell drive is 'd:').
function Get-AbsolutePath {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string[]]
$Path
)
process {
$Path | ForEach-Object {
$PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_)
}
}
}
This library is good: NDepend.Helpers.FileDirectoryPath.
EDIT: This is what I came up with:
[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
}
Call it like this:
> NormalizePath "fred\frog\..\frag"
fred\frag
Note that this snippet requires the path to the DLL. There is a trick you can use to find the folder containing the currently executing script, but in my case I had an environment variable I could use, so I just used that.
Create a function. This function will normalize a path that does not exists on your system as well as not add drives letters.
function RemoveDotsInPath {
[cmdletbinding()]
Param( [Parameter(Position=0, Mandatory=$true)] [string] $PathString = '' )
$newPath = $PathString -creplace '(?<grp>[^\n\\]+\\)+(?<-grp>\.\.\\)+(?(grp)(?!))', ''
return $newPath
}
Ex:
$a = 'fooA\obj\BusinessLayer\..\..\bin\BusinessLayer\foo.txt'
RemoveDotsInPath $a
'fooA\bin\BusinessLayer\foo.txt'
Thanks goes out to Oliver Schadlich for help in the RegEx.
This gives the full path:
(gci 'fred\frog\..\frag').FullName
This gives the path relative to the current directory:
(gci 'fred\frog\..\frag').FullName.Replace((gl).Path + '\', '')
For some reason they only work if frag
is a file, not a directory
.
If the path includes a qualifier (drive letter) then x0n's answer to Powershell: resolve path that might not exist? will normalize the path. If the path doesn't include the qualifier, it will still be normalized but will return the fully qualified path relative to the current directory, which may not be what you want.
$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
Well, one way would be:
Join-Path 'fred\frog' '..\frag'.Replace('..', '')
Wait, maybe I misunderstand the question. In your example, is frag a subfolder of frog?
If you need to get rid of the .. portion, you can use a System.IO.DirectoryInfo object. Use 'fred\frog..\frag' in the constructor. The FullName property will give you the normalized directory name.
The only drawback is that it will give you the entire path (e.g. c:\test\fred\frag).
The expedient parts of the comments here combined such that they unify relative and absolute paths:
[System.IO.Directory]::SetCurrentDirectory($pwd)
[IO.Path]::GetFullPath($dapath)
Some samples:
$fps = '.', 'file.txt', '.\file.txt', '..\file.txt', 'c:\somewhere\file.txt'
$fps | % { [IO.Path]::GetFullPath($_) }
output:
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
참고URL : https://stackoverflow.com/questions/495618/how-to-normalize-a-path-in-powershell
'developer tip' 카테고리의 다른 글
jquery [duplicate]를 사용하여 텍스트로 드롭 다운 값 설정 (0) | 2020.09.20 |
---|---|
ES6 Map과 WeakMap의 차이점은 무엇입니까? (0) | 2020.09.20 |
TypeScript에서 json 파일 가져 오기 (0) | 2020.09.20 |
신속한 변환 범위 (0) | 2020.09.20 |
Oracle SQL 이스케이프 문자 ( '&'용) (0) | 2020.09.20 |