2011-03-28 69 views
338

無論何時我需要引用通用模塊或腳本,我都喜歡使用相對於當前腳本文件的路徑,這樣,我的腳本就可以隨時在庫中找到其他腳本。確定當前PowerShell腳本位置的最佳方法是什麼?

那麼,確定當前腳本目錄的最佳標準方法是什麼?目前,我正在做:

$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 

我知道模塊(名爲.psm1),可以使用$PSScriptRoot得到這個信息,但沒有得到正規的腳本設置(即的.ps1文件)。

獲取當前PowerShell腳本文件位置的規範方法是什麼?

+1

可能重複的[我如何獲取powershell腳本的文件系統位置?](http://stackoverflow.com/questions/3667238/how-can-i-get-the-file-system-location- of-a-powershell-script) – JohnC 2014-04-14 11:09:44

回答

569

PowerShell 3+

# This is an automatic variable set to the current file's/module's directory 
$PSScriptRoot 

PowerShell的2

此前的PowerShell 3,有沒有比查詢 MyInvocation.MyCommand.Definition屬性用於一般腳本更好的辦法。我基本上在每個PowerShell腳本我有頂部 以下行:

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 
+1

這裏使用了什麼'Split-Path'? – CMCDragonkai 2016-12-09 09:06:45

+4

'Split-Path'與'-Parent'參數一起使用,可以返回當前目錄而不包含當前正在執行的腳本名稱。 – hjoelr 2016-12-09 14:55:10

+0

注意:使用Linux/macOS上的PowerShell,您的腳本必須具有用於填充PSScriptRoot/MyInvocation等的.ps1擴展名。在此處查看錯誤報告:https://github.com/PowerShell/PowerShell/issues/4217 – 2018-03-11 05:11:29

13

,也許我失去了一些東西......但如果你想在當前工作目錄你可以使用這個:(Get-Location).Path爲一個字符串,或者一個對象的Get-Location

除非你指的是這樣的東西,這是我在再次閱讀問題後理解的。

function Get-Script-Directory 
{ 
    $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value 
    return Split-Path $scriptInvocation.MyCommand.Path 
} 
+11

這會獲取用戶正在運行腳本**的當前位置**。不是腳本文件**本身**的位置。 – 2011-03-29 00:07:08

+2

'函數獲取腳本目錄 {$ = scriptInvocation(獲取變量MyInvocation -Scope 1).value的 回報拆分路徑$ scriptInvocation.MyCommand.Path } $你好= 「你好」 寫主機( Get-Script-Directory) Write-Host $ hello'保存並從其他目錄運行它。您將顯示腳本的路徑。 – 2011-03-29 00:25:00

+0

這是一個很好的功能,並且做我需要的,但是如何分享它並在我的所有腳本中使用它?這是一個雞和雞蛋的問題:我想使用一個函數來找出我的當前位置,但我需要我的位置來加載函數。 – 2011-03-29 02:26:52

47

如果要創建一個V2模塊,你可以使用一個叫做 $PSScriptRoot自動變量。

從PS>幫助automatic_variable

 
$PSScriptRoot 
     Contains the directory from which the script module is being executed. 
     This variable allows scripts to use the module path to access other 
     resources. 
+9

這就是您在PS 3.0中需要的:$ PSCommandPath 包含正在運行的腳本的完整路徑和文件名。此變量在所有腳本中都有效。「# – CodeMonkeyKing 2013-03-14 06:02:48

+1

剛剛測試過$ PSScriptRoot並按預期工作。但是,如果你在命令行運行它,它會給你一個空字符串。如果在腳本中使用並且腳本被執行,它只會給你結果。這就是它的意思..... – 2013-09-17 04:22:16

+4

我很困惑。這個答案說使用PSScriptRoot for V2。另一個答案是PSScriptRoot適用於V3 +,併爲v2使用不同的東西。 – 2014-05-09 16:35:56

1

你也可以考慮split-path -parent $psISE.CurrentFile.Fullpath如果任何其他方法失敗。特別是,如果你運行一個文件來加載一堆函數,然後在ISE shell中執行這些函數(或者如果你運行選中的話),看起來上面的Get-Script-Directory函數不起作用。

+3

只要您先保存腳本並執行整個文件,'$ PSCommandPath'將在ISE中運行。否則,你實際上並沒有執行腳本。你只是「粘貼」命令到shell中。 – Zenexer 2013-07-25 04:02:04

+0

@Zenexer我認爲那是我當時的目標。雖然如果我的目標與原始目標不匹配,除偶爾的Google員工之外,這可能不會太有用... – 2015-01-16 16:36:06

21

對於PowerShell的3.0

$PSCommandPath 
    Contains the full path and file name of the script that is being run. 
    This variable is valid in all scripts. 

的功能則是:

function Get-ScriptDirectory { 
    Split-Path -Parent $PSCommandPath 
} 
+11

更好的是,使用$ PSScriptRoot。它是當前文件的/模塊的目錄。 – 2014-04-29 17:57:18

+1

這個命令包含了腳本的文件名,這讓我意識到這一點。當你想要路徑時,你可能不希望腳本名稱也在那裏。至少,我想不出你想要這樣的理由。 $ PSScriptRoot不包括文件名(從其他答案中收集)。 – YetAnotherRandomUser 2017-06-21 11:26:38

6

我需要知道腳本的名稱和它是從哪裏執行。

當從主腳本和導入的.PSM1庫文件的主線調用MyInvocation結構時,將前綴「$ global:」返回到完整路徑和腳本名稱。它也可以在導入的庫中的函數中使用。

經過多次擺弄,我決定使用$ global:MyInvocation.InvocationName。 它可以在CMD啓動,運行Powershell和ISE的情況下可靠運行。 本地和UNC啓動都會返回正確的路徑。

+4

** Split-Path -Path $($ global:MyInvocation.MyCommand.Path)**工作完美謝謝。其他解決方案返回調用應用程序的路徑。 – wchoward 2014-05-06 21:24:25

+1

瑣碎的注意事項:在ISE中使用F8/Run Selection調用此函數將觸發'ParameterArgumentValidationErrorNullNotAllowed'異常。 – weir 2015-10-19 14:15:11

-2
function func1() 
{ 
    $inv = (Get-Variable MyInvocation -Scope 1).Value 
    #$inv.MyCommand | Format-List * 
    $Path1 = Split-Path $inv.scriptname 
    Write-Host $Path1 
} 

function Main() 
{ 
    func1 
} 

Main 
7

我使用automatic variable $ ExecutionContext,它可以在PowerShell 2及更高版本中使用。

$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\') 

$ ExecutionContext中 包含表示Windows PowerShell主機的 執行上下文的EngineIntrinsics對象。您可以使用此變量 查找可用於cmdlet的執行對象 。

+1

這是它爲我工作的唯一一個嘗試從STDIN提供PowerShell的工具。 – Sebastian 2017-04-15 16:45:18

+0

當您處於UNC路徑上下文中時,此解決方案也可以正常工作。 – user2030503 2018-02-12 07:50:33

4

花了我一段時間來開發一些東西,採取接受的答案,並將其轉換爲一個強大的功能。

對其他人不太確定,但我在兩臺PowerShell版本2和3的機器環境中工作,所以我需要同時處理這兩種情況。下面的函數提供了一個優美的回退:

Function Get-PSScriptRoot 
{ 
    $ScriptRoot = "" 

    Try 
    { 
     $ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop 
    } 
    Catch 
    { 
     $ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path 
    } 

    Write-Output $ScriptRoot 
} 

這也意味着,該功能是指腳本範圍,而不是家長的範圍由邁克爾Sorens在他blog

+0

謝謝! 「$ script:」是我需要在Windows PowerShell ISE中運行的。 – 2017-01-11 20:20:30

5

非常相似,已經發布的答案概括,但是管道似乎更像PS。

$PSCommandPath | Split-Path -Parent 
2

對於Powershell的3+

function Get-ScriptDirectory { 
    if ($psise) {Split-Path $psise.CurrentFile.FullPath} 
    else {$global:PSScriptRoot} 
} 

我放在這個功能在我的個人資料。在ISE中使用F8/Run Selection也行。

相關問題