【ForEach-Object】PowerShellでパイプからforeachループするテクニック

こんにちは。チェシャ男です。(-皿-)

今回は、

【PowerShell で実行結果をパイプしてループ処理する方法】

について紹介します。

PowerShell では基本的にオブジェクトとしてデータを扱う特徴があるので、配列の時と同じように他のコマンドレットの実行結果もループ処理することができます。

ForEach-Object による基本的なループ処理の方法については、こちら↓の記事をご参考ください。

[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/object/foreach-object/”]

 

他コマンドレットの結果をループする

ループ処理を行うコマンドレット

ForEach-Object

の使い方は以下をご覧ください。

[blogcard url=”https://cheshire-wara.com/powershell/ps-help/foreach-object-help/”]

【コマンドレット】

ForEach-Object

【オプション】

パターン1
[v2 まで] -Begin      <初期化スクリプトブロック{}>
-End       <終了スクリプトブロック{}>
-InputObject   <入力オブジェクト>
-Process     <適用スクリプトブロック{}>

[v3,v4,v5 以降] -Begin      <初期化スクリプトブロック{}>
-End       <終了スクリプトブロック{}>
-InputObject   <入力オブジェクト>
-Process     <適用スクリプトブロック{}>
-RemainingScripts <残りのスクリプトブロック{}>
-Confirm
-WhatIf

パターン2
-MemberName  <メンバー名>
-ArgumentList   <引数リスト>
-InputObject   <入力オブジェクト>
-Confirm
-WhatIf

【入力】

System.Management.Automation.PSObject

【出力】

System.Management.Automation.PSObject

【エイリアス】

ForEach
%

出力結果に対して操作を加える

今回は Get-ChildItem コマンドレットの出力結果に対してループ処理します。”-Name” オプションを使用して名前だけを抽出してみましょう。

PS C:\work> Get-ChildItem -Name
File1.txt
File2.txt
File3.txt
File4.txt
File5.txt

実行結果のように「C:\work」の配下に”File*.txt”というファイルを5つ用意してみました。

出力結果にはファイル名しかないので「フォルダパス(ロケーション) + ファイル名」という操作を行いフルパスに変更してみましょう。

PS C:\work> #フルパスにする
PS C:\work> Ge-hildItem -Name | ForEach-Object -Process { "C:\work\" + $_}
C:\work\File1.txt
C:\work\File2.txt
C:\work\File3.txt
C:\work\File4.txt
C:\work\File5.txt

このように他コマンドレットの実行結果に対し ”ForEach-Object” コマンドレットを使用することでループ処理を行うことができます。

配列の操作時と比べるとほとんど違いはないので、そこまで難しくはないかと思います。

また、コマンドレットの実行結果オブジェクトには多くのメソッドやプロパティが用意されています。これらを使った方法はこちら↓の記事をご参考ください。

[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/object/foreach-object-membername/”]

(ちょっと応用編)初期化処理と終了処理を組み合わせる

他コマンドレットの実行結果をループ処理させる方法も特に難しくなかったと思うので少し応用してみましょう。

先ほどのループ処理でフルパスに変更した結果を配列に格納してみます。初期化処理で配列を宣言し終了処理で画面出力します。

初期化処理(-Begin):配列の宣言

メイン処理(-Process):フルパスに変更 + 配列に代入

終了処理(-End):画面出力

という感じです。

PS C:\work> Get-ChildItem -Name | ForEach-Object -Begin {$array = @() } -Process {$array += "C:\work\" + $_} -End {$array}
C:\work\File1.txt
C:\work\File2.txt
C:\work\File3.txt
C:\work\File4.txt
C:\work\File5.txt

”-Begin” オプションスクリプトブロック内で配列を宣言し、”-End” オプション内で配列を画面表示しています。

また、親ディレクトリ「C:\work\」がべた書きなので初期化処理にまとめてみましょう。$pathという変数を用意して格納します。

PS C:\work> #$pathにファイルパスを格納する
PS C:\work> Get-ChildItem -Name | ForEach-Object -Begin {$array = @(); $path = "C:\work\"} -Process {$array += $path + $_} -End {$array}
C:\work\File1.txt
C:\work\File2.txt
C:\work\File3.txt
C:\work\File4.txt
C:\work\File5.txt

このように工夫次第ではもっと色々できそうですね。

あなたが「だいぶ PowerShell に慣れてきたな~」と思ったら色んな処理を試してみてください!

まとめ

他コマンドレットの実行結果に対してループ処理をしたいときは配列と同様に、

<コマンドレット> | ForEach-object -Process {<処理内容>}

を使用する。

2 COMMENTS

断酒34日

powershellでPDFを結合するときどうするんだ!!

って時に見つけました。

助かりました。

返信する

コメントを残す

メールアドレスが公開されることはありません。