バッチ経由で実行しているPSスクリプトのカレントディレクトリ取得方法
概要
これまで下記のコードで実行中のPowerShellスクリプトが格納されている場所を取得していました。
$currentDirectoryUsingMyInvocation_old = (Split-Path ( & { $MyInvocation.ScriptName } ) -Parent)
より簡潔に取得できる方法を2つ見つけたので紹介します。
この記事のターゲット
- PowerShellユーザーの方
- バッチで実行したPowerShellスクリプト内の処理でカレントディレクトリ(自身の格納場所)を取得する方法を知りたい方
カレントディレクトリを取得するシチュエーション
バッチファイル(*.bat
)経由でPowerShellスクリプトを実行、かつバッチファイルとPowerShellスクリプトの格納場所が異なる場合、
PowerShellスクリプト内のコードで .\
などの相対パスを使うとバッチファイルから見た相対パスとなり正常動作しません。
たとえば下記のような構成の場合 ...
D:\ルートフォルダー
│
├ ExecuteMain.bat
│
└ sourceフォルダー
└ powershellフォルダー
├ Main.ps1
└ setup.ini
ExecuteMain.batでMain.ps1を実行し、かつMain.ps1内で相対パスでsetup.ini
を参照している場合、
PowerShellスクリプト内で .\setup.ini
と使用しても「D:\ルートフォルダー\sourceフォルダー\powershellフォルダー\setup.ini
」と解釈されません。
実際には起動したバッチファイルが元となる為、「D:\ルートフォルダー\setup.ini
」のファイルを参照しようとし、
エラーが発生してしまいます。
上記エラーとなる構成で検証した結果を共有
前述している通りの構成でスクリプトを作成しました。
PS C:\> TREE /F .\ルートフォルダー\
フォルダー パスの一覧: ボリューム OS
ボリューム シリアル番号は 0000XXXX XXXX:XXXX です
C:\ルートフォルダー
│ ExecuteMain.bat
│
└─sourceフォルダー
└─powershellフォルダー
Main.ps1
setup.ini
PS C:\>
下記のバッチファイルでは、PowerShellスクリプトを呼び出しています。
@ECHO OFF
@REM メインスクリプト場所を設定
SET PSFILEPATH="%~dp0sourceフォルダー\powershellフォルダー\Main.ps1"
@REM メインスクリプトを実行
powershell -NoProfile -ExecutionPolicy Unrestricted -File %PSFILEPATH%
@REM 自動で終了するバッチを一時停止
ECHO.
ECHO 処理が終了しました。
ECHO いずれかのキーを押すとウィンドウが閉じます。
PAUSE > NUL
下記のPowerShellスクリプトでは、自身のカレントディレクトリでもある「C:\ルートフォルダー\sourceフォルダー\powershellフォルダー
」の配下、 setup.ini
を参照しようと、
相対パスで.\setup.ini
としています。
このコーディングは直接、PowerShellスクリプトを実行するケースではエラーになりませんが、
前述している通り、バッチファイル起動の場合はエラーとなってしまいます。
# 相対パスでsetup.iniを参照
Get-Item .\setup.ini
設定ファイル(setup.ini
)の内容は参照しない為、雑に記載。
# 参照されない中身をいい加減に記述
SettingColumn01="Setting Contents01"
SettingColumn02="Setting Contents02"
上記の構成・ソースによりバッチファイル経由でPowerShellスクリプトを実行すると、
PowerShellスクリプト内 Get-Item .\setup.ini
の相対パスがバッチファイルをベースとした「C:\ルートフォルダー\setup.ini
」で解釈されてしまいエラーが発生します。
実際のエラーは下記の通り。
Get-Item : パス 'C:\ルートフォルダー\setup.ini' が存在しないため検出できません。
発生場所 C:\ルートフォルダー\sourceフォルダー\powershellフォルダー\Main.ps1:1 文字:1
+ Get-Item .\setup.ini
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\ルートフォルダー\setup.ini:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
処理が終了しました。
いずれかのキーを押すとウィンドウが閉じます。
エラー事例:バッチ起動のPowerShellスクリプトで相対パスを使用した場合
ここまで検証したとおり、バッチファイル経由でPowerShellスクリプトを実行する場合、「.\~
」というように相対パスを使用すると、
バッチファイルを起点としたパスとなる為、すこし回りくどい指定が必要となります。
この記事で紹介する方法を使用する事で、PowerShellスクリプトを起点とした相対パスを使用できます!
対応方法
自動変数「$MyInvocation」を使ったカレントディレクトリの取得方法
$currentDirectoryUsingMyInvocation = (Split-Path -Path $MyInvocation.MyCommand.Path -Parent)
参考情報:以前コーディングしていた「$MyInvocation.ScriptName」を使用した取得方法
冒頭にも紹介しましたが私が以前にコーディングしていた下記の取得方法は、回りくどいですね。上記、「$MyInvocation.MyCommand.Path
」を使用する方法の方がシンプルでわかりやすいです。
$currentDirectoryUsingMyInvocation_old = (Split-Path ( & { $MyInvocation.ScriptName } ) -Parent)
自動変数「$PSScriptRoot」を使ったカレントディレクトリの取得方法
$currentDirectoryUsingPSScriptRoot = $PSScriptRoot
まとめ
-
以前も自動変数
$MyInvocation
を使いPowerShellスクリプトの相対パスを取得していたが、よりシンプルな2つの方法があった- 自動変数
$MyInvocation
を使った、よりシンプルな取得方法 - 自動変数
$PSScriptRoot
を使った、シンプルな取得方法
- 自動変数
-
個人的なオススメの取得方法は、自動変数「
$PSScriptRoot
」を使った方法
理由:処理内容と自動変数の名前が紐づきやすく、わかりやすいため
関連記事
Discussion