PowerShellの「ForEach-Object」完全ガイド:各オブジェクトへの処理を自在に操る方法

PowerShellは、オブジェクト指向型のシェルとして非常に高機能なスクリプト言語を備えています。その中でも「ForEach-Object」コマンドレットは、パイプライン処理で登場する各オブジェクトに対して個別に処理を施すための非常に重要なコマンドです。本記事では、PowerShell初心者から中級者向けに「ForEach-Object」の基本的な使い方から応用テクニックまでを解説します。


ForEach-Objectとは何か?

PowerShellには「foreach」ループと「ForEach-Object」の2種類がありますが、本記事で解説する「ForEach-Object」はパイプライン内で使用されるコマンドレットです。パイプラインを流れる各オブジェクトに対して、個別に処理を実行するのに最適な手段です。

1..5 | ForEach-Object { $_ * 2 }

このコードは、1から5までの数字を2倍にして出力します。$_ は現在処理中のオブジェクトを指します。「ForEach-Object」は、Get-ChildItemGet-Process などの出力結果に対して処理を行いたいときに便利です。


基本的な使い方と構文

「ForEach-Object」の基本的な構文は次のようになります:

 | ForEach-Object { スクリプトブロック }
  • コマンド:対象となるオブジェクトを出力するコマンド。
  • ForEach-Object:各オブジェクトに処理を適用する。
  • { スクリプトブロック }:処理の内容。$_ で現在のオブジェクトを参照。

例1:ファイル名の一覧を大文字に変換して表示

Get-ChildItem | ForEach-Object { $_.Name.ToUpper() }

この例では、カレントディレクトリ内のファイル名をすべて大文字で出力します。


パイプラインとForEach-Objectの関係

パイプライン処理はPowerShellの強力な機能です。複数のコマンドを連結することで、前のコマンドの出力が次のコマンドの入力になります。「ForEach-Object」はこの流れの中に組み込まれており、逐次的に処理を行うため、メモリ効率が良いのが特徴です。

たとえば、大量のログファイルからエラーメッセージを抽出して表示する場合、次のように使います:

Get-Content *.log | ForEach-Object {
if ($_ -like "*ERROR*") { $_ }
}

ファイル全体を一度に読み込むのではなく、1行ずつ処理されるため、大きなログでもメモリ負荷が低くなります。


begin・process・endパラメーターの活用

「ForEach-Object」には、-Begin-Process-Endという3つのパラメーターが用意されています。

Get-Process | ForEach-Object -Begin { "処理開始" } `
-Process { $_.ProcessName } `
-End { "処理終了" }
  • -Begin:最初に1回だけ実行されるブロック
  • -Process:各オブジェクトごとに実行されるブロック(省略可、デフォルトの動作)
  • -End:最後に1回だけ実行されるブロック

この構文を使うことで、処理の前後にメッセージを表示したり、集計処理などに応用できます。


応用:複数の処理を1つのブロックに書く

1つのスクリプトブロック内で、複数のアクションを連続して実行することも可能です。

Get-ChildItem | ForEach-Object {
Write-Host "ファイル名: $($_.Name)"
Write-Host "サイズ: $($_.Length) bytes"
}

このようにすれば、各ファイルに対して名前とサイズをセットで表示するなど、カスタマイズ性の高い処理ができます。


パフォーマンスと使いどころ

「ForEach-Object」はパイプラインでの処理に最適ですが、大量のデータに対してシンプルな繰り返しを行う場合には、foreachループの方が高速な場合があります。

たとえば以下のように使い分けると良いでしょう:

  • ファイルやプロセスの一覧に対して逐一処理 → ForEach-Object
  • 小規模なコレクションを反復処理 → foreachループ

トラブルシューティングとよくあるミス

$_の使い忘れ

Get-Service | ForEach-Object { Name }

上記は間違いです。Name という変数が存在しないため、エラーになります。正しくは:

Get-Service | ForEach-Object { $_.Name }

スクリプトブロック内でreturnを使う

スクリプトブロック内で return を使うと、ForEach-Object の実行が中断されることがあります。代わりに Write-Output などを使いましょう。


他のコマンドレットとの組み合わせ

「ForEach-Object」は以下のようなコマンドと特に相性が良いです。

  • Get-ChildItem(ファイルの処理)
  • Get-Process(プロセスの操作)
  • Get-Service(サービス一覧の操作)
  • Get-Content(ファイル読み取り)
  • Select-Object(オブジェクトのプロパティ抽出)

これらと組み合わせることで、強力で柔軟なスクリプトを構築できます。


まとめ

「ForEach-Object」は、PowerShellでパイプラインを活かした処理をする上で欠かせない存在です。基本的な使い方を理解し、$_-Begin-Process-Endなどの機能を活用することで、より柔軟かつ効率的なスクリプトを書くことが可能になります。実際の業務では、ログの整形やサービス監視、ファイル名の変換など、幅広い場面で役立つでしょう。

PowerShellの力を存分に引き出すためにも、「ForEach-Object」をぜひ習得してみてください。

タイトルとURLをコピーしました