실행중인 스크립트의 소스 경로를 어떻게 찾을 수 있습니까?
이 질문에 이미 답변이 있습니다.
내 실행 스크립트가 실행 된 경로를 알 수 있기를 원합니다.
이것은 종종 $ pwd가 아닙니다.
내 스크립트에 상대적인 폴더 구조에있는 다른 스크립트를 호출해야합니다. 경로를 하드 코딩 할 수는 있지만 "dev"에서 "test"로 승격하려고 할 때 불쾌하고 목에 약간의 고통이 있습니다. "생산".
원래 PowerShell 팀의 Jeffrey Snover 가 게시 한 유비쿼터스 스크립트 ( Skyler의 답변 에서 제공됨)와 Keith Cedirc 및 EBGreen이 게시 한 변형은 모두 심각한 단점이 있습니다. !
아래 코드 는 부모 범위 대신 스크립트 범위를 참조하여이 문제를 극복합니다 .
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
문제를 설명하기 위해 네 가지 방법으로 대상 표현을 평가하는 테스트 도구를 만들었습니다. (괄호로 묶인 용어는 다음 결과 테이블의 키입니다.)
- 인라인 코드 [인라인]
- 인라인 기능, 즉 메인 프로그램의 기능 [인라인 기능]
- 도트 소스 함수, 즉 동일한 함수가 별도의 .ps1 파일로 이동 됨 [도트 소스]
- 모듈 기능, 즉 동일한 기능이 별도의 .psm1 파일 [모듈]로 이동 됨
마지막 두 열은 스크립트 범위 (예 : $ script :) 또는 상위 범위 (-scope 1 사용)를 사용한 결과를 보여줍니다. "script"의 결과는 호출이 스크립트의 위치를 올바르게보고했음을 의미합니다. "모듈"결과는 함수를 호출 한 스크립트가 아니라 함수를 포함하는 모듈의 위치를보고 한 호출을 의미합니다. 이것은 모듈에 함수를 넣을 수 없다는 두 함수의 단점을 나타냅니다.
테이블에서 주목할만한 관찰을 제외하고 모듈 문제를 설정하는 것은 부모 범위 접근 방식 을 사용하는 것이 대부분의 경우 실패 한다는 것입니다 (실제로 성공할 때보 다 두 배 더 자주).
마지막으로 테스트 수단은 다음과 같습니다.
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
}
I am not familiar with what was introduced in PowerShell 2, but it could very well be that script scope did not exist in PowerShell 1, at the time Jeffrey Snover published his example.
I was surprised when, though I found his code example proliferated far and wide on the web, it failed immediately when I tried it! But that was because I used it differently than Snover's example (I called it not at script-top but from inside another function (my "nested twice" example).)
2011.09.12 Update
You can read about this with other tips and tricks on modules in my just-published article on Simple-Talk.com: Further Down the Rabbit Hole: PowerShell Modules and Encapsulation.
You tagged your question for Powershell version 1.0, however, if you have access to Powershell version 3.0 you know have $PSCommandPath
and$PSScriptRoot
which makes getting the script path a little easier. Please refer to the "OTHER SCRIPT FEATURES" section on this page for more information.
We've been using code like this in most of our scripts for several years with no problems:
#--------------------------------------------------------------------
# Dot source support scripts
#--------------------------------------------------------------------
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = Split-Path -Parent $ScriptPath
. $ScriptDir\BuildVars.ps1
. $ScriptDir\LibraryBuildUtils.ps1
. $ScriptDir\BuildReportUtils.ps1
I ran into the same issue recently. The following article helped me solve the problem: http://blogs.msdn.com/powershell/archive/2007/06/19/get-scriptdirectory.aspx
If you're not interested in how it works, here's all the code you need per the article:
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
And then you get the path by simply doing:
$path = Get-ScriptDirectory
I think you can find the path of your running script using
$MyInvocation.MyCommand.Path
Hope it helps !
Cédric
This is one of those oddities (to my mind at least) in PS. I'm sure there is a perfectly good reason for it, but it still seems odd to me. So:
If you are in a script but not in a function then $myInvocation.InvocationName will give you the full path including the script name. If you are in a script and inside a function then $myInvocation.ScriptName will give you the same thing.
Thank you msorens! This really helped me with my custom module. In case anyone is interested in making their own, here is how mine is structured.
MyModule (folder)
- MyModule.psd1 (help New-ModuleManifest)
- MyScriptFile.ps1 (ps1 files are easy to test)
You then reference MyScriptFile.ps1 in MyModule.psd1. Referencing the .ps1 in the NestedModules array will place the functions in the module session state rather than the global session state. (How to Write a Module Manifest)
NestedModules = @('.\MyScriptFile.ps1','.\MyOtherScriptFile.ps1')
Content of MyScriptFile.ps1
function Get-ScriptDirectory {
Split-Path $script:MyInvocation.MyCommand.Path
}
try {
Export-ModuleMember -Function "*-*"
}
catch{}
try / catch는 MyScriptFile.ps1을 실행할 때 Export-ModuleMember에서 오류를 숨 깁니다.
MyModule 디렉터리를 $ env : PSModulePath 에있는 경로 중 하나에 복사합니다 .
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
'developer tip' 카테고리의 다른 글
HelloCordova에서 Ionic 앱의 이름을 바꾸는 방법 (0) | 2020.11.30 |
---|---|
413 요청 엔티티가 너무 큼-파일 업로드 문제 (0) | 2020.11.30 |
시간 부분을 무시하고 T-SQL에서 날짜 비교 (0) | 2020.11.30 |
하나의 작업에 대한 컨트롤러 AuthorizeAttribute 재정의 (0) | 2020.11.30 |
Android : 공백이있는 URL 문자열을 URI 객체로 구문 분석하는 방법은 무엇입니까? (0) | 2020.11.30 |