programing

실행 중인 스크립트의 소스 경로는 어떻게 찾을 수 있습니까?

bestprogram 2023. 10. 9. 23:25

실행 중인 스크립트의 소스 경로는 어떻게 찾을 수 있습니까?

실행 중인 스크립트가 어떤 경로에서 실행되었는지 알 수 있기를 원합니다.
$pwd가 아닌 경우가 많습니다.

내 스크립트와 관련된 폴더 구조에 있는 다른 스크립트를 호출해야 하고 경로를 하드 코드화할 수는 있지만 "개발자"에서 "테스트"로 "프로덕션"으로 승격하려고 할 때는 불쾌하기도 하고 조금 곤란하기도 합니다.

원래 파워셸 팀의 제프리 스노버가 게시한 유비쿼터스 스크립트(스카이러의 답변에 나와 있음)와 키스 세디르와 EBGreen이 게시한 변형 버전 모두 심각한 단점을 겪고 있습니다. 코드가 기대하는 내용을 보고하는지 여부는 코드 이름에 따라 달라집니다.

아래의 내 코드는 상위 범위 대신 스크립트 범위를 단순히 참조함으로써 이 문제를 해결합니다.

function Get-ScriptDirectory
{
    Split-Path $script:MyInvocation.MyCommand.Path
}

이러한 문제점을 설명하기 위해 4가지 방법으로 목표식을 평가하는 테스트 차량을 개발했습니다.(괄호로 표시된 항은 다음 결과표의 키입니다.)

  1. 인라인 코드 [inline]
  2. 인라인 함수, 즉 메인 프로그램의 함수 [inline 함수]
  3. Dot-sourced 함수, 즉 동일한 함수가 별도의 .ps1 파일로 이동됨 [dot sourced]
  4. 모듈 기능, 즉 동일한 기능이 별도의 .psm1 파일로 이동됨 [module]

마지막 두 열에는 스크립트 범위(즉, $script:)를 사용하거나 상위 범위(-scope 1)를 사용한 결과가 표시됩니다."script"의 결과는 호출이 스크립트의 위치를 올바르게 보고했음을 의미합니다."module" 결과는 호출이 함수를 호출한 스크립트가 아니라 함수를 포함하는 모듈의 위치를 보고했음을 의미합니다. 이는 두 함수 모두에서 함수를 모듈에 넣을 수 없다는 단점을 나타냅니다.

모듈 문제를 테이블에서 제외하고 주목할 만한 관찰 사항은 상위 범위 접근 방식을 사용하는 것이 대부분(실제로 성공할 때의 두 배) 실패한다는 것입니다.

table of input combinations

마지막으로 테스트 차량은 다음과 같습니다.

function DoubleNested()
{
    "=== DOUBLE NESTED ==="
    NestCall
}

function NestCall()
{
    "=== NESTED ==="
    "top level:"
    Split-Path $script:MyInvocation.MyCommand.Path
    #$foo = (Get-Variable MyInvocation -Scope 1).Value
    #Split-Path $foo.MyCommand.Path
    "immediate func call"
    Get-ScriptDirectory1
    "dot-source call"
    Get-ScriptDirectory2
    "module call"
    Get-ScriptDirectory3
}

function Get-ScriptDirectory1
{
    Split-Path $script:MyInvocation.MyCommand.Path
    # $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    # Split-Path $Invocation.MyCommand.Path
}

. .\ScriptDirFinder.ps1
Import-Module ScriptDirFinder -force

"top level:"
Split-Path $script:MyInvocation.MyCommand.Path
#$foo = (Get-Variable MyInvocation -Scope 1).Value
#Split-Path $foo.MyCommand.Path

"immediate func call"
Get-ScriptDirectory1
"dot-source call"
Get-ScriptDirectory2
"module call"
Get-ScriptDirectory3

NestCall
DoubleNested

ScriptDirFinder.ps1의 내용:

function Get-ScriptDirectory2
{
    Split-Path $script:MyInvocation.MyCommand.Path
#   $Invocation = (Get-Variable MyInvocation -Scope 1).Value
#   Split-Path $Invocation.MyCommand.Path
}

ScriptDirFinder.psm1의 내용:

function Get-ScriptDirectory3
{
    Split-Path $script:MyInvocation.MyCommand.Path
#   $Invocation = (Get-Variable MyInvocation -Scope 1).Value
#   Split-Path $Invocation.MyCommand.Path
}

PowerShell 2에 소개된 내용을 잘 알지 못하지만 Jeffrey Snover가 예제를 발표할 당시에는 스크립트 범위가 PowerShell 1에 존재하지 않았을 수도 있습니다.

저는 그의 코드 예제가 웹상에 널리 퍼져있는 것을 발견했지만 시도해보니 바로 실패하고 말았습니다!그러나 그것은 Snover의 예와 다르게 사용했기 때문입니다(스크립트톱이 아니라 다른 함수 내부에서 사용했습니다).

2011.09.12 업데이트

Simple-Talk.com 의 published 기사에서 모듈에 대한 다른 팁과 요령을 읽을 수 있습니다.더 아래로 토끼 구멍: 파워쉘 모듈캡슐화.

파워셸 버전 1.0에 대한 질문을 태그했습니다. 그러나 파워셸 버전 3.0에 액세스할 수 있는 경우.$PSCommandPath그리고.$PSScriptRoot그래서 대본 경로를 좀 더 쉽게 알 수 있습니다.자세한 내용은 이 페이지의 "기타 스크립트 기능" 섹션을 참조하십시오.

우리는 몇 년 동안 문제없이 대부분의 스크립트에서 이와 같은 코드를 사용해 왔습니다.

#--------------------------------------------------------------------
# Dot source support scripts
#--------------------------------------------------------------------
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir  = Split-Path -Parent $ScriptPath
. $ScriptDir\BuildVars.ps1
. $ScriptDir\LibraryBuildUtils.ps1
. $ScriptDir\BuildReportUtils.ps1

저는 최근에 같은 문제에 부딪혔습니다.다음 기사가 문제 해결에 도움이 되었습니다: http://blogs.msdn.com/powershell/archive/2007/06/19/get-scriptdirectory.aspx

작동 방식에 관심이 없다면 기사별로 필요한 모든 코드를 소개합니다.

function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}

그 다음에는 다음과 같은 작업을 수행함으로써 성공할 수 있습니다.

$path = Get-ScriptDirectory

내 생각에 당신은 실행중인 스크립트의 경로를 찾을 수 있을 것 같습니다.

$MyInvocation.MyCommand.Path

도움이 되길 바랍니다!

세드릭

이것은 PS에서 (적어도 내 마음에는) 이상한 점들 중 하나입니다.충분히 그럴만한 이유가 있다고 확신하지만, 저는 아직도 이상하게 생각합니다.그래서:

스크립트에는 있지만 함수에는 없는 경우 $myInvocation.호출 이름은 스크립트 이름을 포함한 전체 경로를 제공합니다.스크립트 안에 있고 함수 안에 있으면 $myInvocation.ScriptName에서도 동일한 내용을 제공합니다.

감사합니다 msorens!이것이 맞춤형 모듈 제작에 큰 도움이 되었습니다.만약 누군가가 그들만의 것을 만드는 것에 관심이 있다면, 여기에 내 것이 어떻게 구성되는지가는지가 있습니다.

MyModule (folder)
 - MyModule.psd1 (help New-ModuleManifest)
 - MyScriptFile.ps1 (ps1 files are easy to test)

그런 다음 MyModule.psd1에서 MyScriptFile.ps1을 참조합니다.NestedModules 배열에서 .ps1을 참조하면 함수가 글로벌 세션 상태가 아닌 모듈 세션 상태에 놓이게 됩니다.(Module Manifest 작성 방법)

NestedModules = @('.\MyScriptFile.ps1','.\MyOtherScriptFile.ps1')

MyScript File.ps1의 내용

function Get-ScriptDirectory {
    Split-Path $script:MyInvocation.MyCommand.Path
}

try {
    Export-ModuleMember -Function "*-*"
}
catch{}

시도/캐치는 MyScriptFile.ps1을 실행할 때 Export-ModuleMember에서 오류를 숨깁니다.

여기 $env: 경로 중 하나에 MyModule 디렉토리를 복사합니다.PSM 모듈 경로

PS C:\>Import-Module MyModule
PS C:\>Get-Command -Module MyModule

CommandType     Name                                               ModuleName                                                                                                                                                
-----------     ----                                               ----------                                                                                                                                                
Function        Get-ScriptDirectory                                MyModule  

언급URL : https://stackoverflow.com/questions/801967/how-can-i-find-the-source-path-of-an-executing-script