실행중인 cmdlet의 현재 디렉터리를 가져 오는 방법


202

이 작업은 간단한 작업이지만 실행 된 cmdlet이 성공적으로 위치한 디렉터리의 경로를 얻는 방법에 대한 몇 가지 시도를 보았습니다. 예를 들어, C:\temp\myscripts\mycmdlet.ps1설정 파일이있는 실행 파일에서 변수 C:\temp\myscripts\settings.xml를 저장할 수 있기를 원합니다 .C:\temp\myscriptsmycmdlet.ps1

이것은 작동하는 하나의 솔루션입니다 (약간 번거롭지 만).

$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$settingspath = $directorypath + '\settings.xml'

다른 하나는 테스트 환경에서만 작동하는이 솔루션을 제안했습니다.

$settingspath = '.\settings.xml'

나는 후자의 접근법을 많이 좋아하고 매번 파일 경로를 매개 변수로 파싱하는 것을 선호하지만 개발 환경에서 작동하도록 할 수는 없습니다. 어떻게해야합니까? PowerShell 구성 방법과 관련이 있습니까?


11
이 질문의 모호한 제목으로 인해 (a) 현재 위치 를 참조하는 방법 (디렉토리) 또는 (b) 실행중인 스크립트의 위치 를 참조하는 방법 ( 실행중인 스크립트가있는 디렉토리 (현재 디렉토리 일 수도 있고 아닐 수도 있음)
mklement0

답변:


143

이를 수행하는 신뢰할 수있는 방법은 당신이 보여준 것과 같습니다 $MyInvocation.MyCommand.Path.

상대 경로 사용은 PowerShell의 $ pwd, 응용 프로그램의 현재 디렉토리 또는 .NET API의 현재 작업 디렉토리를 기반으로합니다.

PowerShell v3 + :

자동 변수를 사용하십시오 $PSScriptRoot.


6
PATH 속성을 어떻게 찾았는지 설명해 주시겠습니까? $ MyInvocation.MyCommand | gm은 이러한 속성을 멤버 목록에 표시하지 않습니다.
Vitaliy Markitanov

19
왜 $ PSScriptRoot를 사용하지 않습니까? 더 안정적인 것 같습니다
mBrice1024

@ user2326106 당신은 차이 설명 할 수 $PSScriptRoot$MyInvocation.MyCommand.Path?
duct_tape_coder

1
이 답변은 불완전합니다.
K-SO의 독성이 증가하고 있습니다.

이 답변은 불완전합니다.
stackleit

263

그렇습니다. 그러나 절대 경로를 볼 필요가 있으면 이것이 전부입니다.

(Get-Item -Path ".\").FullName

4
고마워, 이것은 상대 경로에서 전체 경로를 찾는 좋은 방법입니다. 예 (GET-항목 -Path $ myRelativePath -Verbose) .FullName는
dlux

감사합니다. EXE로 컴파일 된 Powershell 스크립트에는 다른 답변이 작동하지 않았습니다.
Zach Alexander

10
이것은 잘못 이다. 이것은 프로세스 의 현재 디렉토리를 가져옵니다 . 예를 들어, 현재 명령 행 current directory가 C:\mydir이고 명령을 호출하면 C:\dir1\dir2\dir3\mycmdlet.ps1C:\mydir아닌으로 해결됩니다 C:\dir1\dir2\dir3. 현재 디렉토리가 상위 프로세스에서 상속되므로 새 실행 파일을 호출하면 동일한 문제점이 있습니다.
jpmc26

85

가장 쉬운 방법은 다음과 같은 사전 정의 된 변수를 사용하는 것 같습니다.

 $PSScriptRoot

about_Automatic_Variables그리고 about_Scripts두 상태 :

PowerShell 2.0에서이 변수는 스크립트 모듈 (.psm1)에서만 유효합니다. PowerShell 3.0부터는 모든 스크립트에서 유효합니다.

나는 이것을 다음과 같이 사용한다 :

 $MyFileName = "data.txt"
 $filebase = Join-Path $PSScriptRoot $MyFileName

12
버전에 따라 다릅니다. 최소한 Powershell 3.0이 필요합니다.
Marvin Dickhaus

1
이것이 스크립트와 동일한 위치에서 파일을 참조하는 데 필요한 것입니다. 감사합니다!
Adam Prescott

이것은 PS 스크립트가 존재하는 경로를 정확하게 제공하므로 본질적으로 스크립트 실행의 근본이되는 가장 좋은 대답입니다. 스크립트를 호출 한 곳에서 현재 작업 디렉토리가 무엇인지 상관하지 않습니다. +1.
RBT

@MarvinDickhaus 그렇기 때문에 대부분의 스크립트에서 "Set-StrictMode -Version 3.0"을 사용해야합니다. :) 큰 감사합니다!
Alexander Shapkin

44

다음을 사용할 수도 있습니다.

(Resolve-Path .\).Path

괄호 안의 부분은 PathInfo객체를 반환 합니다.

PowerShell 2.0부터 사용 가능합니다.


2
이것은 잘못 이다. 이것은 프로세스 의 현재 디렉토리를 가져옵니다 . 예를 들어, 현재 명령 행 current directory가 C:\mydir이고 명령을 호출하면 C:\dir1\dir2\dir3\mycmdlet.ps1C:\mydir아닌으로 해결됩니다 C:\dir1\dir2\dir3. 현재 디렉토리가 상위 프로세스에서 상속되므로 새 실행 파일을 호출하면 동일한 문제점이 있습니다.
jpmc26

3
감사! 나는 또한이 질문의 제목을 잘못 이해 했으며이 대답은 내가 찾던 것과 정확히 일치했습니다. 그러나 ... 그것은 질문에 대답하지 않습니다.
라이언 리치

33

경로는 종종 null입니다. 이 기능은 더 안전합니다.

function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value;
    if($Invocation.PSScriptRoot)
    {
        $Invocation.PSScriptRoot;
    }
    Elseif($Invocation.MyCommand.Path)
    {
        Split-Path $Invocation.MyCommand.Path
    }
    else
    {
        $Invocation.InvocationName.Substring(0,$Invocation.InvocationName.LastIndexOf("\"));
    }
}

1
왜 -Scope 1입니까? not
-Scope

1
Get-Variable : 범위 번호 '1'이 (가) 활성 범위 수를 초과합니다.
suiwenfeng

2
부모 범위가 없기 때문에이 오류가 발생합니다. -Scope 매개 변수는 지정된 범위의 변수를 가져옵니다. 이 경우 1은 상위 범위입니다. 자세한 내용은 Get-Variable ( technet.microsoft.com/en-us/library/hh849899.aspx ) 에 대한이 Technet 기사를 참조하십시오.
Christian Flem



11

나는 한 줄 해결책을 좋아 한다 :)

$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

이것이 지금까지 가장 좋은 솔루션입니다.
Teoman shipahi

그렇습니다. 내 pwd는 내 사용자 디렉토리이고 다른 디렉토리에서 스크립트를 실행하고 있습니다. (B) 그것이 제공하는 (B)
andrew pate


4

Powershell 3 이상에서는 간단히 사용할 수 있습니다

$PSScriptRoot


1

경로로 '. \'를 사용하는 것이 호출 경로임을 의미한다고 생각할 것입니다. 그러나 항상 그런 것은 아닙니다. 예를 들어 작업 ScriptBlock 내에서 사용하는 경우입니다. 이 경우 % profile % \ Documents를 가리킬 수 있습니다.


1

이 함수는 프롬프트 위치를 스크립트 경로로 설정하여 vscode, psise 및 pwd 사이의 스크립트 경로를 얻는 다른 방법을 처리합니다.

function Set-CurrentLocation
{
    $currentPath = $PSScriptRoot                                                                                                     # AzureDevOps, Powershell
    if (!$currentPath) { $currentPath = Split-Path $pseditor.GetEditorContext().CurrentFile.Path -ErrorAction SilentlyContinue }     # VSCode
    if (!$currentPath) { $currentPath = Split-Path $psISE.CurrentFile.FullPath -ErrorAction SilentlyContinue }                       # PsISE

    if ($currentPath) { Set-Location $currentPath }
}

0

가치가있는 것, 한 줄짜리 솔루션이 되려면 아래가 나를 위해 작동하는 솔루션입니다.

$currFolderName = (Get-Location).Path.Substring((Get-Location).Path.LastIndexOf("\")+1)

끝에 1은을 무시하는 것 /입니다.

Get-Location cmdlet을 사용한 위 게시물에 감사합니다 .


0

다음 IDE에서 디버깅 할 때 대부분의 답변이 작동하지 않습니다.

  • PS-ISE (PowerShell ISE)
  • VS 코드 (Visual Studio Code)

그것들에서는 $PSScriptRoot비어 있고 Resolve-Path .\(그리고 비슷한) 경로가 잘못되기 때문입니다.

Freakydinde의 답변 은 이러한 상황을 해결하는 유일한 방법이므로 투표를했지만 Set-Location그 답변이 실제로 원하는 것이라고 생각하지 않습니다 . 그래서 나는 그것을 고치고 코드를 좀 더 명확하게 만들었습니다.

$directorypath = if ($PSScriptRoot) { $PSScriptRoot } `
    elseif ($psise) { $psise.CurrentFile.FullPath } `
    elseif ($psEditor) { split-path $psEditor.GetEditorContext().CurrentFile.Path }

-1

@Cradle의 답변을 확장하려면 OP의 질문에 따라 동일한 결과를 얻을 수있는 다목적 함수 를 작성할 수도 있습니다 .

Function Get-AbsolutePath {

    [CmdletBinding()]
    Param(
        [parameter(
            Mandatory=$false,
            ValueFromPipeline=$true
        )]
        [String]$relativePath=".\"
    )

    if (Test-Path -Path $relativePath) {
        return (Get-Item -Path $relativePath).FullName -replace "\\$", ""
    } else {
        Write-Error -Message "'$relativePath' is not a valid path" -ErrorId 1 -ErrorAction Stop
    }

}

-1

현재 디렉토리의 이름 만 있으면 다음과 같이 할 수 있습니다.

((Get-Location) | Get-Item).Name

C : \ Temp \ Location \ MyWorkingDirectory>에서 작업한다고 가정합니다.

산출

MyWorkingDirectory


-1

비슷한 문제가 있었고 PowerShell (전체 최종 사용자 GUI 응용 프로그램)으로 작성된 프로그램을 만들고 디스크에서로드 해야하는 많은 파일과 리소스가 있기 때문에 많은 문제가 발생했습니다. 내 경험상 .현재 디렉토리를 나타내는 데 사용 하는 것은 신뢰할 수 없습니다. 현재 작업 디렉토리를 나타내야하지만 종종 그렇지 않습니다. PowerShell은 내부에서 PowerShell이 ​​호출 된 위치를 저장하는 것으로 보입니다 .. 보다 정확하게 말하면 PowerShell이 ​​처음 시작될 때 기본적으로 홈 사용자 디렉토리 내에서 시작됩니다. 일반적으로 사용자 계정의 디렉토리입니다.C:\USERS\YOUR USER NAME. 그런 다음 PowerShell은 디렉토리를 호출 한 디렉토리 또는 PowerShell 프롬프트를 표시하거나 스크립트를 실행하기 전에 실행중인 스크립트가있는 디렉토리로 디렉토리를 변경합니다. 그러나 PowerShell 앱 자체가 원래 홈 사용자 디렉토리에서 시작된 후에 발생합니다.

그리고 .PowerShell이 ​​시작된 초기 디렉터리를 나타냅니다. 그래서 .당신이 원하는 디렉토리에서 PowerShell을 호출하는 경우에만 경우 현재 디렉토리를 나타냅니다. 나중에 PowerShell 코드에서 디렉토리를 변경하면 변경 내용이 .모든 경우에 반영되는 것은 아닙니다 . 어떤 경우에는 .현재 작업중인 디렉토리를 나타내며 다른 경우에는 PowerShell (스크립트 자체가 아닌)이 호출 된 디렉토리에서 결과가 일치하지 않을 수 있습니다. 이런 이유로 호출자 스크립트를 사용합니다. 내부에 단일 명령이 포함 된 PowerShell 스크립트 : POWERSHELL. 그러면 원하는 디렉토리에서 PowerShell을 호출하여.현재 디렉토리를 나타냅니다. 그러나 나중에 PowerShell 코드에서 디렉토리를 변경하지 않으면 작동합니다. 스크립트의 경우 파일 옵션을 포함한다는 점을 제외하고 마지막으로 언급 한 호출자 스크립트를 사용합니다 POWERSHELL -FILE DRIVE:\PATH\SCRIPT NAME.PS1. 그러면 현재 작업 디렉토리 내에서 PowerShell이 ​​시작됩니다.

스크립트를 클릭하기 만하면 스크립트 위치에 관계없이 홈 사용자 디렉토리에서 PowerShell이 ​​호출됩니다. 결과적으로 현재 작업 디렉토리는 스크립트가있는 디렉토리이지만 PowerShell 호출 디렉토리 는 상황이며 상황에 따라이 두 디렉토리 중 하나 C:\USERS\YOUR USER NAME.반환합니다.

그러나 이러한 모든 혼란을 피하고 호출자 스크립트를 사용하려면 현재 작업 디렉토리 또는 스크립트가 호출 된 디렉토리를 나타내는 날씨에 따라 현재 디렉토리를 나타내는 대신 $PWD또는 $PSSCRIPTROOT대신에 단순히 또는 대신을 사용할 수 있습니다 .. 그리고 어떤 이유로 든 .반환 하는 두 디렉토리 중 다른 디렉토리를 검색 하려면을 사용할 수 있습니다 $HOME.

필자는 개인적으로 내 앱의 루트 디렉토리 내에 호출자 스크립트를 가지고 있으며 주 앱 스크립트를 호출하는 PowerShell을 사용하여 개발하며 앱의 소스 코드 내에서 현재 작업 디렉토리를 절대로 변경하지 않아야한다는 것을 기억하므로 걱정할 필요가 없습니다. .현재 디렉토리를 나타내고 문제없이 응용 프로그램에서 상대 파일 주소 지정을 지원 하는 데 사용할 수 있습니다 . 이것은 최신 버전의 PowerShell (버전 2 이상)에서 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.