PowerShell:スクリプトのディレクトリからコマンドを実行します


144

スクリプトの現在のディレクトリを使用していくつかのことを行うPowerShellスクリプトがあります。したがって、そのディレクトリ内では、実行.\script.ps1は正しく機能します。

スクリプトの参照ディレクトリを変更せずに、別のディレクトリからそのスクリプトを呼び出したいと思います。だから私は呼び出し..\..\dir\script.ps1たいのですが、そのスクリプトがディレクトリ内から呼び出されたときと同じように動作します。

それを行う方法、またはスクリプトを変更して任意のディレクトリから実行できるようにする方法を教えてください。

回答:


200

スクリプトの横にあるファイルを参照できるように、スクリプト自体のパスが必要ですか?これを試して:

$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 $folder

# do stuff, call ant, etc

# now back to previous directory
Pop-Location

Invoke-Commandを使用して同様のことを実現するには、おそらく他の方法もあるでしょう。


1
ええと、ええと、多分私は自分のスクリプトについてもう少し明確にするべきでした。実際には、antいくつかのパラメーターを指定して呼び出すスクリプトです。そのantため、そのフォルダーから呼び出して、構成ファイルが正しく検出されるようにする必要があります。理想的には、スクリプト内でローカルに実行ディレクトリを一時的に変更するための何かを探しています。
2011年

3
ああ、その場合には、あなたが望むだろうPush-LocationPop-Location
JohnL

5
$ MyInvocationは状況依存です。通常、$ ScriptPath =(Get-Variable MyInvocation -Scope Script).Value.MyCommand.Pathを実行します。これは、あらゆる種類の入れ子または関数から機能します
Ion Todirel

39

ネイティブアプリを呼び出す場合[Environment]::CurrentDirectoryは、PowerShellの$PWD現在のディレクトリを気にする必要はありません。さまざまな理由により、PowerShellはSet-LocationまたはPush-Locationのときにプロセスの現在の作業ディレクトリを設定しないため、設定が必要なアプリケーション(またはコマンドレット)を実行している場合は、必ずそうする必要があります。

スクリプトでは、これを行うことができます:

$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によって自動的に設定されない理由に関する2つのメモ:

  1. PowerShellはマルチスレッド化できます。単一のプロセス内で同時に実行される複数のRunspaces(RunspacePoolおよびPSThreadJobモジュールを参照)を持つことができます。各ランスペースには独自の$PWD現在の作業ディレクトリがありますが、プロセスは1つ、環境は1つしかありません。
  2. シングルスレッドの場合でも、$PWD必ずしも合法的なCurrentDirectory であるとは限りません(たとえば、レジ​​ストリプロバイダーにCDを挿入する場合があります)。

それをプロンプトに入れたい場合(メインの実行空間でのみ実行され、シングルスレッド)、以下を使用する必要があります。

[Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem

4
これは、ため、パスプロバイダのプロセスの作業ディレクトリを変更しません:あなたは、レジストリにCD'ingされる可能性があります、SQLデータベースまたはIISハイブなどを...
piers7

1
はい。それが最後の「最終メモ」のポイントでした。他のすべてのシェルと同様に、(プロンプト機能で行うように)ファイルシステムプロバイダーの現在の場所に更新することができます。
Jaykul 2013年

2
神聖なスクリプトの神々、私はとても失望しています.\_/.—これは私の一日の半分を殺したからです!人、真剣に?真剣に?..
ulidtko 2014

2
現在ではほとんど不要です。PowerShellのより新しいバージョンでは、バイナリアプリを起動するときに作業ディレクトリが設定されます。
Jaykul 2017年

1
このメソッドは、[Environment]::CurrentDirectoryとは異なる場合、元の復元に失敗します$PWD。正しいことは、それを変数に格納し、$origEnvDir = [Environment]::CurrentDirectory後で復元すること[Environment]::CurrentDirectory = $origEnvDirです。
Strom、

37

投票数の多い回答がありますが、質問を読んだとき、スクリプトが実行されているディレクトリではなく、スクリプトが置かれているディレクトリを知りたいと思っていました。powershellの自動変数で情報を取得できます

$PSScriptRoot - the directory where the script exists, not the target directory the script is running in
$PSCommandPath - the full path of the script

たとえば、Visual Studioソリューションファイルを検索して開始する$ profileスクリプトがあります。ソリューションファイルが起動したら、完全なパスを保存したいと思いました。しかし、元のスクリプトが存在するファイルを保存したいと思いました。そこで、$ PsScriptRootを使用しました。


12

次のコードをよく使用して、実行中のスクリプトと同じディレクトリにあるモジュールをインポートしました。最初にpowershellが実行されているディレクトリを取得します

$ currentPath = Split-Path((Get-Variable MyInvocation -Scope 0).Value).MyCommand.Path

import-module "$ currentPath \ sqlps.ps1"


-ScopeをScript
Ion Todirel

9

これはうまくいきます。

Push-Location $PSScriptRoot

Write-Host CurrentDirectory $CurDir

Pop-Location最後に呼び出してパスを元の状態に戻すことを忘れないでください。
Lam Le

2

まあ、CLIだけからのスクリプトなしで、しばらくの間、この解決策を探していました。これがxDのやり方です。

  • スクリプトを実行するフォルダに移動します(重要なことはタブ補完があることです)

    ..\..\dir

  • 次に、場所を二重引用符で囲み、その中にaddを追加してcd、Powershellの別のインスタンスを呼び出すことができるようにします。

    "cd ..\..\dir"

  • で区切られたスクリプトを実行する別のコマンドを追加;します。

    "cd ..\..\dir\; script.ps1"

  • 最後に、powershellの別のインスタンスで実行します

    start powershell "cd..\..\dir\; script.ps1"

これにより、新しいPowerShellウィンドウが開き、に移動して..\..\dir実行しscript.ps1、ウィンドウを閉じます。


ご了承ください ";" コマンドを1つずつ入力したように、コマンドを分離するだけです。最初に失敗した場合、2番目に実行され、次に実行されます。新しいPowerShellウィンドウを開いたままにしたい場合は、渡されたコマンドに-noexitを追加します。タブ補完を使用できるように、最初に目的のフォルダーに移動することに注意してください(二重引用符で囲むことはできません)。

start powershell "-noexit cd..\..\dir\; script.ps1"

""名前にスペースを含むディレクトリを渡すことができるように、二重引用符を使用します。たとえば、

start powershell "-noexit cd '..\..\my dir'; script.ps1"


0

私は@JohnLの解決策からワンライナーを作りました:

$MyInvocation.MyCommand.Path | Split-Path | Push-Location
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.