2011-03-28 140 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也行。

相关问题