Join-Path를 사용하여 두 개 이상의 문자열을 파일 경로로 결합하는 방법은 무엇입니까?


105

두 문자열을 파일 경로로 결합하려면 다음 Join-Path과 같이 사용 합니다.

$path = Join-Path C: "Program Files"
Write-Host $path

그게 인쇄 "C:\Program Files"됩니다. 그래도 두 개 이상의 문자열에 대해이 작업을 수행하려면 :

$path = Join-Path C: "Program Files" "Microsoft Office"
Write-Host $path

PowerShell에서 오류가 발생합니다.

Join-Path : 'Microsoft Office'인수를 허용하는 위치 매개 변수를 찾을 수 없습니다.
D : \ users \ ma \ my_script.ps1 : 1 char : 18
+ $ path = join-path <<<< C : "Program Files" "Microsoft Office"
+ CategoryInfo : InvalidArgument : (:) [Join-Path] , ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound, Microsoft.PowerShell
.Commands.JoinPathCommand

문자열 배열을 사용해 보았습니다.

[string[]] $pieces = "C:", "Program Files", "Microsoft Office"
$path = Join-Path $pieces
Write-Host $path

그러나 PowerShell은 -childpath"somepath"와 같은 자식 경로 ( 인수를 지정하지 않았으므로)를 입력하라는 메시지를 표시 한 다음 세 개의 파일 경로를 만듭니다.

C:\somepath
Program Files\somepath
Microsoft Office\somepath

어느 쪽도 옳지 않습니다.

답변:


171

.NET Path 클래스를 사용할 수 있습니다 .

[IO.Path]::Combine('C:\', 'Foo', 'Bar')

3
확실히 가장 간결한 형식이며 경로 조각에서 경로 구분 기호와 후행 / 선행 슬래시를 올바르게 처리하지만 현재 허용되는 답변 (기본 문자열 연결)에서는 수행하지 않습니다.
David Keaveny 2015

3
내 powershell에서 위의 명령을 실행하려면이 오류가 발생합니다.- "Combine"및 인수 개수 : "3"에 대한 오버로드를 찾을 수 없습니다. 줄 : 1 char : 19 + [io.path] :: combine <<<< ( 'c : \', 'foo', 'bar') + CategoryInfo : NotSpecified : (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest
Aamol

@Aamol 실행중인 CLR 버전 ( $PSVersionTable) 은 무엇입니까 ? 합니까의 [io.path]::combine([string[]]('c:\','foo','bar'))작업?
Marek Toman 2016 년

1
매개 변수 한계가 3 인 것 같습니다. 3 이후 첫 번째 매개 변수는 무시됩니다. (최소한 여기에서는 ps 5.1, clr 4.0)
ehiller 2017

4
@DavidKeaveny "경로 조각에서 경로 구분 기호와 후행 / 선행 슬래시를 제대로 처리합니다."-실제로는 그렇지 않습니다. join-path당신이 기대하는 것을, 않습니다 join-path "C:\" "\foo"출력 C:\foo, Path.Combine그러나 2 번째의 인수가 선도 분리 포함 할 때마다 첫 번째 인수 무시 [io.path]::combine('c:\', '\foo')성가 시게 출력을 \foo.
Quantic

99

Join-Path는 경로 값으로 파이프 될 수 있으므로 여러 Join-Path 문을 함께 파이프 할 수 있습니다.

Join-Path "C:" -ChildPath "Windows" | Join-Path -ChildPath "system32" | Join-Path -ChildPath "drivers"

원하는만큼 간결하지는 않지만 완전히 PowerShell이며 비교적 읽기 쉽습니다.


3
+1 모든 powershell 2,3,4에서 작동하므로 [io.path] :: Combine API의 문제는 .net 프레임 워크 3,4
Ram

18

PowerShell을 6.0 때문에,이 경로-가입 새 매개 변수 전화를 -AdditionalChildPath할 수 있습니다 경로 아웃 - 오브 - 박스의 여러 부분을 결합 . 추가 매개 변수를 제공하거나 요소 목록 만 제공하면됩니다.

문서의 예 :

Join-Path a b c d e f g
a\b\c\d\e\f\g

따라서 PowerShell 6.0 이상에서는 변형

$path = Join-Path C: "Program Files" "Microsoft Office"

예상대로 작동합니다!


17

Join-Path는 정확히 당신이 찾고있는 것이 아닙니다. 여러 용도가 있지만 찾고있는 용도는 아닙니다. Join-Path를 사용한 파티 의 예 :

Join-Path C:\hello,d:\goodbye,e:\hola,f:\adios world
C:\hello\world
d:\goodbye\world
e:\hola\world
f:\adios\world

문자열 배열을 받아들이고 하위 문자열을 각 전체 경로에 연결하는 것을 볼 수 있습니다. 귀하의 예에서 $path = join-path C: "Program Files" "Microsoft Office". 세 개의 위치 인수를 전달하고 join-path두 개만 허용 하므로 오류가 발생합니다 . 당신이 찾고있는 것은이며 -join, 이것이 오해임을 알 수 있습니다. 대신 귀하의 예에서 이것을 고려하십시오.

"C:","Program Files","Microsoft Office" -join "\"

-Join항목의 배열을 가져 와서 \단일 문자열로 연결합니다 .

C:\Program Files\Microsoft Office

인양을위한 사소한 시도

예, 이 답변 이 더 낫다 는 데 동의 하지만 여전히 작동 할 수 있습니다. 주석은 슬래시에 문제가있을 수 있음을 암시하므로 내 연결 방식을 유지하려면이 작업도 수행 할 수 있습니다.

"C:","\\Program Files\","Microsoft Office\" -join "\" -replace "(?!^\\)\\{2,}","\"

따라서 추가 슬래시에 문제가있는 경우 문자열의 시작 부분에 있지 않는 한 처리 할 수 ​​있습니다 ( UNC 경로 허용 ). [io.path]::combine('c:\', 'foo', '\bar\')예상대로 작동하지 않으며 내 것이 설명합니다. 모든 시나리오를 설명 할 수는 없으므로 둘 다 입력에 적절한 문자열이 필요합니다. 두 가지 접근 방식을 모두 고려하십시오. 그러나 다른 높은 등급의 답변은 더 간결하며 그것이 존재하는지조차 몰랐습니다.

또한 지적하고 싶습니다. 제 대답은 핵심 문제를 해결하기위한 제안을 제공하는 것 외에도 OP가 어떻게 잘못되었는지 설명합니다.


2
경로에서 여러 개의 연속 된 \이 작동하더라도보기 흉하고 잠재적으로 문제를 일으킬 수 있기 때문에 잘못된 것입니다.
Mikhail Orlov 2015 년

@MikhailOrlov 잠재적 인 문제가 발생할 수 있다고 제안하는 것으로 설명 할 수 있습니까? 다른 제안이 있습니까? 나는 문제가 보이지 않기 때문에 묻는다. 문제가 있으면 해결하고 싶습니다.
Matt

2
나는 최근에 많은 저품질 코드를 처리해 왔으며 사람들은 String.Equals로 경로를 비교하고 빈 문자열을 제거하지 않고 String.Split ( '\\')로 경로를 구문 분석합니다. 결과적으로 더 위험한 것은 생각할 수 없습니다. 대부분은 편집증에 불과합니다. 수정 해주셔서 감사합니다.
Mikhail Orlov 2015 년

3
경로 구분자를 명시 적으로 포함하면 플랫폼 간 이식성에 문제가 발생할 수 있습니다. PowerShell은 현재 Windows에서만 실행되지만 멀지 않은 미래에 변경 될 가능성이 있으므로 가능한 한 빨리 좋은 습관을 개발하는 것이 좋습니다. 이러한 습관이 다른 언어로 옮겨 질 수 있다는 것은 말할 것도 없습니다.
bshacklett 2015

10

여전히 .NET 2.0을 사용 하는 경우 두 개 이상의 부분을 결합하는 데 필요한 오버로드 [IO.Path]::Combine가 없으며 "결합"에 대한 오버로드를 찾을 수 없음params string[] 오류 와 인수 개수 : "3"이 표시됩니다.

약간 덜 우아하지만 순수한 PowerShell 솔루션은 경로 부분을 수동으로 집계하는 것입니다.

Join-Path C: (Join-Path  "Program Files" "Microsoft Office")

또는

Join-Path  (Join-Path  C: "Program Files") "Microsoft Office"

5

다음은 ChildPath에 문자열 배열을 사용할 때 원하는 작업을 수행하는 것입니다.

$path = "C:"
@( "Program Files", "Microsoft Office" ) | %{ $path = Join-Path $path $_ }
Write-Host $path

어떤 출력

C:\Program Files\Microsoft Office

내가 찾은 유일한주의 사항은 $ path의 초기 값에 값이 있어야한다는 것입니다 (null이거나 비어있을 수 없음).


4

임의의 수의 구성 요소를 경로에 결합하는 순수 PowerShell 함수를 작성하는 두 가지 방법이 더 있습니다.

이 첫 번째 함수는 단일 배열을 사용하여 모든 구성 요소를 저장 한 다음 foreach 루프를 사용하여 결합합니다.

function Join-Paths {
    Param(
        [Parameter(mandatory)]
        [String[]]
        $Paths
    )
    $output = $Paths[0]
    foreach($path in $Paths[1..$Paths.Count]) {
        $output = Join-Path $output -ChildPath $path
    }
    $output
}

경로 구성 요소는 배열의 요소이고 단일 인수의 모든 부분이므로 쉼표로 구분해야합니다. 사용법은 다음과 같습니다.

PS C : \> Join-Paths 'C :', 'Program Files', 'Microsoft Office'
C : \ Program Files \ Microsoft Office


이 함수를 작성하는보다 간단한 방법은 내장 $args변수를 사용한 다음 Mike Fair의 방법을 사용하여 foreach 루프를 한 줄로 축소하는 것입니다.

function Join-Paths2 {
    $path = $args[0]
    $args[1..$args.Count] | %{ $path = Join-Path $path $_ }
    $path
}

이전 버전의 함수와 달리 각 경로 구성 요소는 별도의 인수이므로 인수를 구분하려면 공백 만 있으면됩니다.

PS C : \> Join-Paths2 'C :' '프로그램 파일' 'Microsoft Office'
C : \ Program Files \ Microsoft Office

2

다음 접근 방식은 Join-Path 문을 파이핑하는 것보다 더 간결합니다.

$p = "a"; "b", "c", "d" | ForEach-Object -Process { $p = Join-Path $p $_ }

$ p는 연결된 경로 'a \ b \ c \ d'를 보유합니다.

(나는 이것이 Mike Fair의 접근 방식과 똑같은 접근 방식이라는 것을 알았습니다. 죄송합니다.)


1

또는 자신의 함수를 작성할 수 있습니다 (이것이 내가 한 일입니다).

function Join-Path-Recursively($PathParts) {
    $NumberOfPathParts = $PathParts.Length;

    if ($NumberOfPathParts -eq 0) {
        return $null
    } elseif ($NumberOfPathParts -eq 1) {
        return $PathParts[0]
    } else {
        return Join-Path -Path $PathParts[0] -ChildPath $(Join-Path-Recursively -PathParts $PathParts[1..($NumberOfPathParts-1)])
    }
}

그런 다음 다음과 같이 함수를 호출 할 수 있습니다.

Join-Path-Recursively -PathParts  @("C:", "Program Files", "Microsoft Office")
Join-Path-Recursively  @("C:", "Program Files", "Microsoft Office")

이는 .NET Framework에 의존하지 않고 일반 Join-Path 함수와 똑같은 동작을하는 이점이 있습니다.


0

다음과 같이 사용할 수 있습니다.

$root = 'C:'
$folder1 = 'Program Files (x86)'
$folder2 = 'Microsoft.NET'

if (-Not(Test-Path $(Join-Path $root -ChildPath $folder1 | Join-Path -ChildPath $folder2)))
{
   "Folder does not exist"
}
else 
{
   "Folder exist"
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.