自動変数
PowerShell Coreには実行中にPowerShell Coreによって生成される変数がある。この変数は「自動変数」と呼ばれており、リードオンリーでの利用が想定されている。機能として自動変数を上書きすることはできるのだが、互換性の面からそういった利用はしない方がよいとされている。
PowerShell Coreに用意されている主な自動変数は次のとおり。
自動変数 | 意味 |
---|---|
$NULL | NULLまたは空値を保持 |
$TRUE | TRUEを保持 |
$FALSE | FALSEを保持 |
$? | 最後に実行した操作の可否を保有。成功した場合にはTRUE、失敗した場合にはFALSE |
$$ | セッションが最後に受け取った行の最後のトークン |
$^ | セッションが最後に受け取った行の最初のトークン |
$ARGS | 関数、スクリプト、スクリプトブロックなどに渡されたパラーメタの配列 |
$CONSOLEFILENAME | セッションで最後に実行されたコンソールファイル(.psc1)のパス |
$ERROR | エラーメッセージが保持された配列。もっとも最後のエラーは$ERROR[0]に保持される |
$EVENT | 処理されているイベントのPSEventArgsオブジェクトを保持 |
$EVENTARGS | 処理されているイベントのEventArgsから派生した最初のイベント引数を示すオブジェクトを保持 |
$EVENTSUBSCRIBER | 処理されているイベントのイベントサブスクライバを示すPSEventSubscriberオブジェクトを保持 |
$EXECUTIONCONTEXT | PowerShellホストの実行コンテキストを意味するEngineIntrinsicsオブジェクトを保持 |
$FOREACH | ForEachループの列挙子を保持 |
$HOME | ユーザのホームディレクトリパスを保持 |
$HOST | PowerShellの現在のホストアプリケーションを示すオブジェクトを保持 |
$INPUT | 関数に渡されるすべてのインプットを示す列挙子を保持 |
$LASTEXITCODE | 最後に実行されたWindowsベースプログラムの終了コードを保持 |
$MATCHES | -matchオペレータおよび-notmatchオペレータとともに動作する$Matches変数 |
$MYINVOCATION | 現在のコマンド(名前、パラメータ、パラメータ変数、コマンドが実行された方法など)に関する情報を保持 |
$NESTEDPROMPTLEVEL | 現在のプロンプトレベルを保持 |
$PID | プロセス番号を保持 |
$PROFILE | 現在のユーザおよび現在のホストアプリケーションに対するPowerShellプロファイルのフルパスを保持 |
$PSBOUNDPARAMETERS | スクリプトや関数に渡されるパラーメタのディクショナリおよび現在の値を保持 |
$PSCMDLET | 実行されているコマンドレットまたはアドバンスド関数を示すオブジェクトを保持 |
$PSCOMMANDPATH | 実行されているスクリプトのファイル名およびフルパスを保持 |
$PSCULTURE | 現在実行されているオペレーティングシステムの文化名を保持 |
$PSDEBUGCONTEXT | デバッグ中にデバッグ情報を保持 |
$PSHOME | PowerShellがインストールされているディレクトリのフルパスを保持 |
$PSITEM | パイプラインオブジェクトにおける現在のオブジェクトを保持。$_に同じ |
$PSSCRIPTROOT | スクリプトが実行されているディレクトリを保持 |
$PSSENDERINFO | PSSessionを開始したユーザに関する情報を保持。ユーザ情報やタイムゾーンなどの情報を含む |
$PSUICULTURE | オペレーティングシステムで使われているユーザインターフェース文化名を含む |
$PSVERSIONTABLE | 現在のセッションで実行されているPowerShellのバージョン情報を示すハッシュテーブルを保持 |
$PWD | カレントディレクトリのフルパスを示すオブジェクトを保持 |
$SENDER | 対象イベントによって生成されたオブジェクトを保持 |
$SHELLID | 現在のシェル情報を保持 |
$STACKTRACE | エラーを示すスタックトレースを保持 |
$THIS | スクリプトプロパティやスクリプトメソッドを定義するスクリプトブロックにおいて拡張されているオブジェクトを参照 |
すべての自動変数を覚える必要はなく、必要なものだけ覚えておけばよい。以降でよく使うことになる自動変数とその使用例を取り上げる。
$TRUEと$FALSE
スクリプトを書いていると、ロジック的にここに処理がきた場合にはエラーとして処理したいとか、逆にコマンドの実行結果が成功していても失敗していても成功として処理させたいことがある。UNIX系オペレーティングシステムのシェルスクリプトであればtrueとfalseというコマンドが存在しているので、これを使うことになる。
trueアプリケーション - PowerShell Core/macOS
PS /Users/daichi> Get-Command true | Format-List
Name : true
CommandType : Application
Definition : /usr/bin/true
Extension :
Path : /usr/bin/true
FileVersionInfo : File: /usr/bin/true
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
PS /Users/daichi>
falseアプリケーション - PowerShell Core/macOS
PS /Users/daichi> Get-Command false | Format-List
Name : false
CommandType : Application
Definition : /usr/bin/false
Extension :
Path : /usr/bin/false
FileVersionInfo : File: /usr/bin/false
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
PS /Users/daichi>
しかし、このコマンドはWindowsには存在しておらず、実行しようとすれば次のようにエラーになる。
自動変数の$TRUEおよび$FALSEはそういった場合に利用できる。この変数を利用すればtrueやfalseといったコマンドが存在しないプラットフォームでも処理が機能することになる。
$?
$?は直前に実行したコマンドが成功しているか失敗しているかを保持する自動変数だ。常に成功するtrueと常に失敗するfalseというアプリケーション(UNIX系オペレーティングシステムのコマンド)を使って動作を確認すると次のようになる。
直前のコマンドが成功した場合の$?の中身
PS /Users/daichi> true
PS /Users/daichi> echo $?
True
PS /Users/daichi>
直前のコマンドが失敗した場合の$?の中身
PS /Users/daichi> false
PS /Users/daichi> echo $?
False
PS /Users/daichi>
この自動変数は直前のコマンドの実行を監視して、失敗した場合にはエラーメッセージを出すようにするとか、何らかの処理をリトライするとか、そういった動作をさせる場合に利用できる。
これを簡単に書くと次のようになる。
直前のコマンドが成功している場合には何もしない
PS /Users/daichi> true
PS /Users/daichi> if (! $?) { echo "failed." }
PS /Users/daichi>
直前のコマンドが失敗している場合にはエラーメッセージを出力
PS /Users/daichi> false
PS /Users/daichi> if (! $?) { echo "failed." }
failed.
PS /Users/daichi>
例えば、ネットワークを経由してほかのホストにファイルをコピーするような処理を書いたとする。それはscpでもftpでもなんでもよいのだが、ネットワークを経由してほかのホストにコピーするような処理では、必ずしも処理が成功するとは限らない。
そういった場合、コマンドが成功裏に終了したかどうかを調べ、失敗している場合にはある程度の時間待機してからもう一度同じコマンドを実行するといった処理を行うことがある。$?を使うとそうした処理を実現できる。
$ARGS
PowerShellスクリプトを書くようになると関数を作成する機会が増えると思うが、こういった場合に引数が格納されるのが$ARGSだ。
引数の利用例
PS /Users/daichi> function f() { echo $ARGS }
PS /Users/daichi> f a b c d
a
b
c
d
PS /Users/daichi>
基本的な機能なので覚えておく必要がある。
$HOMEと$PWD
$HOMEにはホームディレクトリ、$PWDにはカレントディレクトリが保持される。どちらも使う機会のある自動変数だ。
$HOMEはユーザのホームディレクトリ以下のデータにアクセスする場合に利用するし、$PWDはカレントディレクトリによって処理を変えたい場合などに利用する。
$ERRORと$STACKTRASE
インタラクティブシェルとして利用している場合も、シェルスクリプトとして利用している場合も、問題が発生した場合のデバッグに利用できる変数が$ERRORと$STACKTRASEだ。
$Errorが保持しているエラー情報
PS /Users/daichi> echo $Error
At line:1 char:3
+ if $(! $?)
+ ~
Missing '(' after 'if' in if statement.
s : The term 's' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:2
+ ;s
+ ~
+ CategoryInfo : ObjectNotFound: (s:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS /Users/daichi>
$StackTraceが保持しているスタックトレース情報
PS /Users/daichi> echo $StackTrace
at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandTypes commandTypes, SearchResolutionOptions searchResolutionOptions, CommandOrigin commandOrigin, ExecutionContext context)
at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin, ExecutionContext context)
at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandName, CommandOrigin commandOrigin)
at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(String commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)
at System.Management.Automation.ExecutionContext.CreateCommand(String command, Boolean dotSource)
at System.Management.Automation.PipelineOps.AddCommand(PipelineProcessor pipe, CommandParameterInternal[] commandElements, CommandBaseAst commandBaseAst, CommandRedirection[] redirections, ExecutionContext context)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
PS /Users/daichi>
すべての自動変数を覚える必要はないが、今回取り上げたような自動変数は利用する機会が多いのでおさえておきたいところだ。
参考資料
- Microsoft PowerShell Module Browser
- Microsoft PowerShell6|Microsoft.PowerShell.Core|About|About Variables
- Microsoft PowerShell6|Microsoft.PowerShell.Core|About|About Automatic Variables
- Microsoft PowerShell6|Object Pipeline
- Microsoft PowerShell6|Understanding the Windows PowerShell Pipeline
- Microsoft PowerShell6|Microsoft.PowerShell.Core|Get-Command
- Microsoft PowerShell6|Microsoft.PowerShell.Utility|Format-List
- Microsoft PowerShell6|About Regular Expressions
- Microsoft PowerShell6|Microsoft.PowerShell.Utility|Get-Member
- Microsoft PowerShell6|Microsoft.PowerShell.Management|Get-Item
- Microsoft PowerShell6|Microsoft.PowerShell.Management|Get-ChildItem