在PowerShell中包含相关文件

63

我想使用这样的伪语法来引入脚本文件:

Include '.\scripA.ps1'

但我找到的唯一一件事是像这样的东西:

$thisScript = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
. ($thisScript + '.\scriptA.ps1')

那很难看。

有没有一些好看的方法来使用相对路径包含脚本?

7个回答

129
你可以像这样利用$PSScriptRoot参数:

你可以像这样利用$PSScriptRoot参数:

. "$PSScriptRoot\script.ps1"

2
我发现这对于在Azure ARM模板VM CustomScriptExtension中下载多个文件到存储帐户blob容器并使用FileUris参数调用引用其他文件的一个文件非常有用。Azure文档并没有很有帮助地指导如何确定下载文件的相对路径。我尝试了. .\path\to\script.ps1,当您从Windows资源管理器或PS终端在同一文件夹中运行脚本时它可以工作,但在部署到Azure时它一直失败。这个答案完全解决了这个问题。 - theyetiman

30

您可以点命令,即将该文件包含进来:

. .\scriptA.ps1

要获取脚本的完整路径:

Resolve-Path .\scriptA.ps1


1
第一部分执行...但是Resolve-Path将检查当前目录和路径以查找文件。如果您的脚本目录在路径($env:path)中,它将找到它。 - Steven Murawski
谢谢大家,我应该提到当前位置。 - Shay Levy
对我有用。谢谢 +1 - yO_

21

虽然如前所述,点号调用是最简单的选项但不太美观。然而,使用这种格式稍微更加整洁一些:

$ScriptDirectory = Split-Path $MyInvocation.MyCommand.Path
. (Join-Path $ScriptDirectory ScriptA.ps1)

另外,关于相对路径的一点需要明确的说明:原帖子可能似乎想要一个相对于当前工作目录的路径;但实际上意图是相对于当前脚本源目录(正如alex2k8自己的代码示例所表明的那样)。因此,这使得当前脚本能够访问同一代码库中的其他脚本。


8
很不幸,没有好的方法。在V1版本中,PowerShell并不是很好地支持这个想法。实际上,你采取的方法是最好的方法。

而v2呢?我应该使用模块来管理外部脚本和"Import-Module ./foo.psm1"语法吗?还是常规脚本的包含有任何改进? - alex2k8
@alex2k8,我还没有在V2上做过太多的工作,所以我不能提供太多帮助。我知道模块应该比脚本更加隔离,但除此之外,我没有太多的数据。 - JaredPar
在v2中,您可以使用一个带有清单的模块来定义所有模块、脚本,甚至是snapins/程序集。这样做的一个好处是,您可以拥有仅对该模块私有的函数和变量。 - JasonMArcher
1
注意:从V2版本开始,您可以轻松引用包含文件,请参见下面的答案。 - Ralph Willgoss
2
在PowerShell 3.0中,您可以使用“.(Join-Path $PSScriptRoot settings.ps1)”(以点号开头的命令)。 - Walter A

6

从V2版本开始(本地版本在Win7/2008R2上启动;请参见$psversiontable.psversion),您可以轻松地包含一个文件,如下所示:

. "RelativeOrAbsolutePathToFile\include.ps1"

$result = FunctionInIncludeFile()

参考:
如何在脚本中重复使用Windows Powershell功能


7
据我所知,这个问题在于点-源行相对于当前工作目录而非包含点-源行的脚本进行评估。因此,如果您首先使用 cd 到包含脚本的目录,它就可以正常运行,但如果您从另一个目录调用它,则无法正常运行。 - user87453
那可能是有意为之的,不过还是谢谢你的评论,伙计! - Ralph Willgoss

2
最初的回答:
你可以使用$PSScriptRoot以及"Split-Path"命令来使相对路径的工作更加清晰。 . (($PSScriptRoot | Split-Path | Split-Path)+'somedir\ps\script.ps1')

0

这个方法可能适用于任何目录,但如果您的起始目录不是要包含的文件的直接前置目录,则查找速度会非常慢。也就是说,如果您搜索的起点是c:\或其他驱动器的根目录,那么这可能会非常慢。

. $(Resolve-Path -literal $(gci -Recurse include.ps1))

如果您在PC上开发脚本,但需要将它们部署到作为计划任务运行脚本的服务器上,则此方法特别有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接