日々PowerShellと戯れていますが、コマンドレットを実行した結果を変数に格納しない日はありません。
そして、変数に格納されたオブジェクトが自分が意図したものになっているか確認しない日もありません。
そんなときはこのようにしています。
変数の中身を確認するために、変数を呼び出しています。
しかしあるとき思いました。
「・・・まどろっこしいな」と。
どうせなら結果を確認しつつ、変数に格納すればいいじゃないか。
そうだ、PowerShellにはTee-Objectコマンドレットがあるじゃないか!!
そう、Tee-Objectコマンドレットを使えば、コマンドの出力をコンソールに出しつつ、変数やファイルに出力することができるのです。
Tee-Objectコマンドレットとは
Tee-ObjectのTeeはTという文字のように2つの方向にリダイレクトできますよ、という意味だそうです。
it sends the output of a command in two directions (like the letter T)
Tee-Object (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs より
まさに「T」という文字のごとく、2方向にリダイレクトするためのコマンドレットになります。
コンソールに出力しつつ変数に格納したいとき
Get-ChildItemの結果をコンソールに出力しつつ、myChildrenという変数に格納するときは次のようにします。
Get-ChildItem|Tee-Object -Variable myChildren
-Variableパラメータに与えた文字列を変数名として解釈して新しい変数が作成されます。
上述の書き方でもいいのですが、私はちょっとだけ楽をするために次のように書くことが多いです。
dir|tee -V myChildren
teeはTee-ObjectのAliasとして標準で登録されています。
どちらも結果は同じですが、他の人の目に触れる可能性があるときはなるべく省略せずに書いた方が無難ですね。
コンソールに出力されているということは、そのオブジェクトをパイプで他のコマンドレットに渡すことも可能です。
Get-ChildItemコマンドレットの結果をTee-Objectで受けつつ$AllItem変数に格納し、さらにそれをWhere-Objectコマンドレットでフィルター処理を行い、結果をさらにTee-Objectに渡すことで$Container変数に格納しつつ、コンソールに出力するというものです。
Get-ChildItem -Recurse |Tee-Object -Variable AllItem |Where-Object{$_.psiscontainer}|Tee-Object -Variable Container
ワンライナーながら、各処理工程をしっかり変数に残すことができるというプチテクニックです。
コンソールに出力しつつファイルに書き込みたいとき
要領は先ほどの変数に格納するときと同じです。
使用するパラメータが-Variableではなく、-FilePathになります。
Get-ChildItem|Tee-Object -FilePath "C:\tee.txt"
注意点としてはC:\tee.txtというファイルが既にある場合は上書きされてしまう点です。
ファイルを上書きせずに追記したい場合ばAppendパラメータを使えば追記することができます。
Get-ChildItem|Tee-Object -FilePath "C:\tee.txt" -Append
終わりに
「T」という文字のようにオブジェクトを2つに出力できるTee-Objectコマンドレットについて紹介しました。
「Tee」というunixを使ったことがない日本人にはあまりイメージがわきづらい動詞のせいで、便利であるにも関わらずマイナーな扱いを受けているような気がする・・・。
そもそもTeeという動詞を使っているコマンドレットは、このコマンドレットしかなく、多分これからも増えることはないと思いますが・・・。
(PowerShell7.0の時点)
でも大丈夫!!君はとっても便利だぞ、Tee-Object!
負けるな、Tee-Object!
というわけで、ここまでお読みいただき、ありがとうございました。