スクリプトファイルの場所 [PowerShell]
場所が知りたい
PowerShell スクリプトの実行中に、そのファイルと同じフォルダに置かれた他のファイルにアクセスしたい場合があります。たとえば、スクリプトを複数ファイルに分割して記述していて、実行中に他のファイルをドットソーシングで読み込む場合です。もちろん他のファイルの場所を自由に配置可能として、起動パラメターでその場所を指定したりするような設計も可能ですが、その場合ですら初期値としてはすべての関連スクリプトファイルを同じフォルダに置くことにするのが便利でしょう。そのためには、スクリプト内で自ファイルの置かれている場所を取得する必要があります。
ここで必要となる、スクリプトの呼び出し関連の情報は自動変数 $myInvocation に格納されています。ただし呼び出し方とスクリプト内の位置に応じて格納されている情報の内容が変わるように見えて、最初は使い方がわかりにくかったので忘れないように書き留めておきます。
結論を先に述べてしまうと、自ファイルの場所の取得には次のような記述が便利です。これで変数 myd に実行中のスクリプトファイルの場所が取得できます。
ここから、なぜこのようにスクリプトブロックを用いて少しばかり面倒な記述をするのかを説明します。
$myInvocation に格納されるスクリプト起動情報
スクリプトの起動に関する情報は自動変数 $myInvocation に格納されています。$myInvocation は System.Management.Automation.InvocationInfo 型であり、次のようなプロパティを持っています。
ScriptName にはスクリプトのフルパス名が格納されます。したがって、これを Split-Path で分解すればスクリプトの置かれている場所を取得することができます。ただし、それは何らかの関数またはスクリプトブロックの中で取得された場合に限ります。どの関数やスクリプトブロックの中にも入らない一番外側のレベルで呼ばれた場合には空になります。また、ドットソーシングで他のスクリプトから呼ばれたスクリプト内の場合、一番外側のレベルでは ScriptName に呼び出した側のスクリプトファイルのフルパス名が入っています。
したがって、そのコードを記述する位置を気にせずいつも望みの結果を得るためには、一段スクリプトブロックの中に入ってScriptNameを取得する、前述の常套句が便利となるのです。
実は、ScriptNameには $myInvocation にアクセスしたコード上の位置を呼び出した場所のスクリプトファイルの名前が入っているという意味では一貫しています。ScriptNameの取得場所と呼び出し方で分類してみると次のようになります。(この説明での“関数”には“スクリプトブロック”も含みます。PowerShellではスクリプトブロックは名前の無い関数と考えられます。)
動作を確かめるためのサンプルコードや、$myInvocationの他のプロパティについても後日書きたいと思っています。
PowerShell スクリプトの実行中に、そのファイルと同じフォルダに置かれた他のファイルにアクセスしたい場合があります。たとえば、スクリプトを複数ファイルに分割して記述していて、実行中に他のファイルをドットソーシングで読み込む場合です。もちろん他のファイルの場所を自由に配置可能として、起動パラメターでその場所を指定したりするような設計も可能ですが、その場合ですら初期値としてはすべての関連スクリプトファイルを同じフォルダに置くことにするのが便利でしょう。そのためには、スクリプト内で自ファイルの置かれている場所を取得する必要があります。
ここで必要となる、スクリプトの呼び出し関連の情報は自動変数 $myInvocation に格納されています。ただし呼び出し方とスクリプト内の位置に応じて格納されている情報の内容が変わるように見えて、最初は使い方がわかりにくかったので忘れないように書き留めておきます。
結論を先に述べてしまうと、自ファイルの場所の取得には次のような記述が便利です。これで変数 myd に実行中のスクリプトファイルの場所が取得できます。
$myd = & { Split-Path $myInvocation.ScriptName }
ここから、なぜこのようにスクリプトブロックを用いて少しばかり面倒な記述をするのかを説明します。
$myInvocation に格納されるスクリプト起動情報
スクリプトの起動に関する情報は自動変数 $myInvocation に格納されています。$myInvocation は System.Management.Automation.InvocationInfo 型であり、次のようなプロパティを持っています。
$myInvocation のプロパティ
CommandLineParameters (Version 2 から)
CommandOrigin (Version 2 から)
ExpectingInput (Version 2 から)
InvocationName
Line
MyCommand
OffsetInLine
PipelineLength
PipelinePosition
PositionMessage
ScriptLineNumber
ScriptName
UnboundArguments (Version 2 から)
ScriptName にはスクリプトのフルパス名が格納されます。したがって、これを Split-Path で分解すればスクリプトの置かれている場所を取得することができます。ただし、それは何らかの関数またはスクリプトブロックの中で取得された場合に限ります。どの関数やスクリプトブロックの中にも入らない一番外側のレベルで呼ばれた場合には空になります。また、ドットソーシングで他のスクリプトから呼ばれたスクリプト内の場合、一番外側のレベルでは ScriptName に呼び出した側のスクリプトファイルのフルパス名が入っています。
したがって、そのコードを記述する位置を気にせずいつも望みの結果を得るためには、一段スクリプトブロックの中に入ってScriptNameを取得する、前述の常套句が便利となるのです。
実は、ScriptNameには $myInvocation にアクセスしたコード上の位置を呼び出した場所のスクリプトファイルの名前が入っているという意味では一貫しています。ScriptNameの取得場所と呼び出し方で分類してみると次のようになります。(この説明での“関数”には“スクリプトブロック”も含みます。PowerShellではスクリプトブロックは名前の無い関数と考えられます。)
- [取得場所] スクリプトファイルの一番外側レベル
[取得内容] スクリプトファイルを呼び出したスクリプトファイルのフルパス名- [呼び出し方] コマンドラインからスクリプトファイルA.ps1を呼ぶ
[取得内容] 呼び出したスクリプトファイルが無いので空白 - [呼び出し方] スクリプトファイルB.ps1からA.ps1を呼ぶ
[取得内容] 呼び出したのはB.ps1なのでそのフルパス名
- [呼び出し方] コマンドラインからスクリプトファイルA.ps1を呼ぶ
- [取得場所] 関数内
[取得内容] 関数を呼び出したスクリプトファイルのフルパス名。呼び出される関数が定義された場所がどのスクリプトファイルであるのかは関係ない。- [呼び出し方] コマンドラインからスクリプトファイルA.ps1内で定義された関数を呼ぶ
[取得内容] 呼び出したスクリプトファイルが無いので空白 - [呼び出し方] スクリプトファイルA.ps1から同じファイル内で定義された関数を呼ぶ
[取得内容] 呼び出したのはA.ps1なのでそのフルパス名 - [呼び出し方] スクリプトファイルB.ps1からA.ps1内で定義された関数を呼ぶ
[取得内容] 呼び出したのはB.ps1なのでそのフルパス名
- [呼び出し方] コマンドラインからスクリプトファイルA.ps1内で定義された関数を呼ぶ
動作を確かめるためのサンプルコードや、$myInvocationの他のプロパティについても後日書きたいと思っています。
タグ:powershell
2008-12-21 10:59
nice!(0)
コメント(0)
トラックバック(0)
コメント 0