2011-03-28 4 views
338

一般的なモジュールやスクリプトを参照する必要があるときは、現在のスクリプトファイルに相対的なパスを使用するのが好きです。私のスクリプトはライブラリ内の他のスクリプトを常に見つけることができます。現在のPowerShellスクリプトの場所を確認する最適な方法は何ですか?

したがって、現在のスクリプトのディレクトリを決定する最も良い、標準的な方法は何ですか?現在、私がやっている:

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

を私は(.psm1)あなたは、この情報を取得するために$PSScriptRootを使用することができますが、それは通常のスクリプト(すなわち、.ps1というファイル)に設定されませんモジュールに知っています。

現在のPowerShellスクリプトファイルの場所を取得するには、どのような方法がありますか?

+1

[可能なファイルシステムの場所を得る方法は?](http://stackoverflow.com/questions/3667238/how-can-i-get-the-file-system-location- of-a-powershell-script) – JohnC

答えて

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プロパティをクエリより良い方法はありませんでした。

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

ここでは 'Split-Path'とは何ですか? – CMCDragonkai

+4

'Split-Path'は' -Parent'パラメータと共に使用され、現在実行中のスクリプトの名前なしで現在のディレクトリを返します。 – hjoelr

+0

注:Linux/macOSのPowerShellでは、スクリプトにPSScriptRoot/MyInvocationなどの.ps1拡張子を設定する必要があります。以下のバグレポートをご覧ください:https://github.com/PowerShell/PowerShell/issues/4217 –

13

はたぶん私はここに何かが欠けている...しかし、あなたは現在の作業ディレクトリをしたい場合は、ちょうどこの使用することができます:用(Get-Location).Pathを私が持っていた、本質的に、すべてのPowerShellスクリプトの先頭に 次の行を持っていました文字列、またはオブジェクトの場合はGet-Locationです。

あなたがこのようなものを参照していない限り、私は再び質問を読んだ後で理解します。

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

これは、ユーザーがスクリプト**を実行している現在の場所**を取得します。スクリプトファイル**の場所ではありません**。 –

+2

'関数は、Get-スクリプト・ディレクトリを { $ scriptInvocation =(取得-変数MyInvocation -Scope 1).Valueの リターン分割経路$ scriptInvocation.MyCommand.Path } $ハロー= "hello" を 書き込みホスト( Get-Script-Directory) Write-Host $ hello'これを保存し、別のディレクトリから実行します。スクリプトへのパスが表示されます。 –

+0

それは良い機能ですが、私が必要とすることはしますが、どのように共有してすべてのスクリプトで使用できますか?それは鶏と卵の問題です:私は現在の場所を見つけるために関数を使いたいと思いますが、関数をロードするために私の場所が必要です。 –

47

あなたはV2モジュールを作成している場合、あなたは $PSScriptRootと呼ばれる自動変数を使用することができます。

PSから>他の方法のいずれかが失敗した場合あなたはまたsplit-path -parent $psISE.CurrentFile.Fullpathを検討するかもしれない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

+1

$ PSScriptRootをテストし、期待どおりに動作しています。ただし、コマンドラインで実行すると空文字列が返されます。それは、スクリプトで使用され、スクリプトが実行された場合にのみ結果を与えるでしょう。それはそれが意味するものです..... –

+4

私は混乱しています。この回答は、PSScriptRootをV2に使用すると述べています。もう1つの答えは、PSScriptRootはV3 +用であり、v2用に別のものを使用することです。 –

1

を助けます。特に、ファイルを実行して一連の関数をロードし、ISEシェル(または実行時に選択した場合)でこれらの関数を実行すると、上記のような関数Get-Script-Directoryが機能しないようです。 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. 

機能については

+3

'$ PSCommandPath'は、スクリプトを最初に保存してファイル全体を実行する限り、ISEで動作します。それ以外の場合は、実際にスクリプトを実行していません。シェルにコマンドを単に貼り付けるだけです。 – Zenexer

+0

@Zenexer私はそれが当時の私の目標だったと思います。私のゴールが元のゴールと一致しない場合は、Google Googlerを除いてこれが役に立たないかもしれません... –

21

は次のようになります。私は、スクリプト名を知るために必要なとどこから実行している

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

さらに便利なのは、$ PSScriptRootです。現在のファイル/モジュールのディレクトリです。 –

+1

このコマンドには、スクリプトのファイル名が含まれています。あなたがそのパスを欲しているときには、あなたはおそらくそこにスクリプト名を入れたくないでしょう。少なくとも、私はあなたがそれを望む理由を考えることができません。 $ PSScriptRootにはファイル名は含まれていません(他の回答から集められたもの)。 – YetAnotherRandomUser

6

"$ global:"をMyInvocation構造体にプレフィックスすると、メインスクリプトとインポートされた.PSM1ライブラリファイルのメインラインの両方から呼び出されたときにフルパスとスクリプト名が返されます。また、インポートされたライブラリの関数内で動作します。

多くの手探りで、$ global:MyInvocation.InvocationNameを使用して解決しました。 CMDの起動、Powershellの実行、ISEで確実に動作します。 ローカルとUNCの両方の起動が正しいパスを返します。

+4

** Split-Path -Path $($ global:MyInvocation.MyCommand.Path)**は完璧に感謝しました。他のソリューションは呼び出し元のアプリケーションのパスを返しました。 – wchoward

+1

簡潔な注意:ISEでは、F8/Run Selectionを使用してこの関数を呼び出すと、 'ParameterArgumentValidationErrorNullNotAllowed'例外が発生します。 – weir

-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オブジェクトが含まれています。 この変数を使用して、コマンドレットで使用できる の実行オブジェクトを見つけることができます。

+1

これは私のために働いていた唯一のもので、STDINからpowershellをフィードしようとしています。 – Sebastian

+0

このソリューションは、UNCパスコンテキストでも正しく動作します。 – user2030503

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 
} 

をまた彼のblog

+0

ありがとう! "$ script:"は、Windows PowerShell ISEでこれを動作させるために必要なものでした。 –

5

にマイケルSorensによって概説としての機能が既に答えを掲載非常によく似スクリプトスコープではなく、親のスコープを参照していることを意味し、配管はPSのように見える。

$PSCommandPath | Split-Path -Parent 
2

は、PowerShellの3+

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

のために私は自分のプロファイルにこの機能を配置しました。 F8/Run Selectionを使用してISEで動作します。