【发布时间】:2011-06-11 02:11:27
【问题描述】:
我有一个 PowerShell 脚本,它使用脚本的当前目录执行一些操作。因此,在该目录中,运行 .\script.ps1 可以正常工作。
现在我想在不更改脚本的引用目录的情况下从不同的目录调用该脚本。所以我想调用..\..\dir\script.ps1 并且仍然希望该脚本的行为与从其目录中调用的一样。
我该怎么做,或者我如何修改脚本以便它可以从任何目录运行?
【问题讨论】:
标签: powershell
我有一个 PowerShell 脚本,它使用脚本的当前目录执行一些操作。因此,在该目录中,运行 .\script.ps1 可以正常工作。
现在我想在不更改脚本的引用目录的情况下从不同的目录调用该脚本。所以我想调用..\..\dir\script.ps1 并且仍然希望该脚本的行为与从其目录中调用的一样。
我该怎么做,或者我如何修改脚本以便它可以从任何目录运行?
【问题讨论】:
标签: powershell
你的意思是你想要脚本自己的路径,这样你就可以引用脚本旁边的文件吗?试试这个:
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
Write-host "My directory is $dir"
您可以从 $MyInvocation 及其属性中获得大量信息。
如果要引用当前工作目录中的文件,可以使用 Resolve-Path 或 Get-ChildItem:
$filepath = Resolve-Path "somefile.txt"
编辑(基于 OP 的评论):
# temporarily change to the correct folder
Push-Location $dir
# do stuff, call ant, etc
# now back to previous directory
Pop-Location
可能还有其他方法可以使用 Invoke-Command 实现类似的功能。
【讨论】:
ant 的脚本。所以我必须从该文件夹中调用ant 以确保它正确找到配置文件。理想情况下,我正在寻找一些东西来临时更改该脚本中本地的执行目录。
Push-Location 和Pop-Location
$MyInvocation.MyCommand.Path | Split-Path | Push-Location
有很多投票的答案,但是当我阅读您的问题时,我以为您想知道脚本所在的目录,而不是脚本运行的目录。您可以通过 powershell 的自动变量获取信息
$PSScriptRoot # the directory where the script exists, not the
# target directory the script is running in
$PSCommandPath # the full path of the script
例如,我有一个 $profile 脚本,它可以找到一个 Visual Studio 解决方案文件并启动它。一旦解决方案文件启动,我想存储完整路径。但我想保存原始脚本所在的文件。所以我使用了$PsScriptRoot。
【讨论】:
如果您正在调用本机应用程序,则需要担心 [Environment]::CurrentDirectory 而不是 PowerShell 的 $PWD 当前目录。由于各种原因,PowerShell 在您设置位置或推送位置时不会设置进程的当前工作目录,因此如果您正在运行期望设置它的应用程序(或 cmdlet),则需要确保这样做。
在脚本中,您可以这样做:
$CWD = [Environment]::CurrentDirectory
Push-Location $MyInvocation.MyCommand.Path
[Environment]::CurrentDirectory = $PWD
## Your script code calling a native executable
Pop-Location
# Consider whether you really want to set it back:
# What if another runspace has set it in-between calls?
[Environment]::CurrentDirectory = $CWD
没有万无一失的替代方案。我们中的许多人在我们的提示函数中添加了一行来设置 [Environment]::CurrentDirectory ...但是当您在脚本中更改位置时,这对您没有帮助。在中。
关于 PowerShell 不自动设置的原因的两个注意事项:
$PWD 当前工作目录,但只有一个进程和一个环境。$PWD 也并不总是合法的 CurrentDirectory(例如,您可以 CD 到注册表提供程序)。如果你想把它放到你的提示符中(它只会在主运行空间中运行,单线程),你需要使用:
[Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem
【讨论】:
.\_/. — 这让我半天的时间都死了!人,认真的吗?认真吗?..
[Environment]::CurrentDirectory 与$PWD 不同时,此方法无法恢复。正确的做法是将其存储到变量$origEnvDir = [Environment]::CurrentDirectory 中,然后再将其恢复为[Environment]::CurrentDirectory = $origEnvDir。
这样就可以了。
Push-Location $PSScriptRoot
Write-Host CurrentDirectory $CurDir
【讨论】:
Pop-Location 以将路径恢复到原始状态。
我经常使用以下代码来导入与运行脚本位于同一目录下的模块。它将首先获取运行powershell的目录
$currentPath=Split-Path ((Get-Variable MyInvocation -Scope 0).Value).MyCommand.Path
导入模块“$currentPath\sqlps.ps1”
【讨论】:
我用@JohnL 的解决方案做了一个单行:
$MyInvocation.MyCommand.Path | Split-Path | Push-Location
【讨论】:
好吧,我一直在寻找解决方案,而没有任何仅来自 CLI 的脚本。我就是这样做的xD:
导航到您要从中运行脚本的文件夹(重要的是您有选项卡完成)
..\..\dir
现在用双引号将位置括起来,并在其中添加cd,这样我们就可以调用另一个powershell实例。
"cd ..\..\dir"
添加另一个命令以运行以;分隔的脚本,其中是powershell中的命令分隔符
"cd ..\..\dir\; script.ps1"
最后用另一个powershell实例运行它
start powershell "cd..\..\dir\; script.ps1"
这将打开新的 powershell 窗口,转到 ..\..\dir,运行 script.ps1 并关闭窗口。
注意“;”只是分隔命令,就像您一个接一个地键入它们一样,如果第一个失败,第二个将运行,然后再运行,然后再运行...如果您想保持新的 powershell 窗口打开,您可以在传递的命令中添加 -noexit 。请注意,我首先导航到所需的文件夹,以便可以使用制表符完成(不能用双引号括起来)。
start powershell "-noexit cd..\..\dir\; script.ps1"
使用双引号 "",这样您就可以传递名称中带有空格的目录,例如,
start powershell "-noexit cd '..\..\my dir'; script.ps1"
【讨论】: