トピック about_Foreach 簡易説明 項目のコレクションに含まれるすべての項目を順番に処理するための言語コマンドについて説明します。 詳細説明 Foreach ステートメント (Foreach ループとも呼ばれます) は、項目のコレクションを構成する 一連の値を 1 つずつ処理する (反復処理する) ための言語構造です。 反復処理で使用する、最も一般的で簡単な型は、配列です。 Foreach ループ内では、配列内の各項目に対して 1 つ以上のコマンドを実行するのが一般的です。 構文 Foreach の構文を次に示します。 foreach ($<item> in $<collection>){<statement list>} コマンド パイプライン外の Foreach ステートメント Foreach ステートメントのかっこで囲まれている部分は、反復処理する変数とコレクションを示 しています。Windows PowerShell では、Foreach ループの実行時に、変数($<item>) が自動的に 作成されます。ループの反復処理を毎回実行する前に、コレクション内の値が変数に設定されます。 Foreach ステートメントに続くブロック {<statement list>} には、コレクション内の各項目に 対して実行する一連のコマンドを指定します。 例 たとえば、次の例にある Foreach ループでは、$letterArray という配列の値が表示されます。 $letterArray = "a","b","c","d" foreach ($letter in $letterArray) { Write-Host $letter } この例では、$letterArray 配列が作成され、文字列値 "a"、"b"、"c"、および "d" で初期化され ます。Foreach ステートメントが最初に実行されると、$letterArray の最初の項目 ("a") が $letter 変数に設定されます。次に、Write-Host コマンドレットを使用して a という文字が表 示されます。次のループ処理では、"b" が $letter に設定され、以下同様の動作が続きます。 Foreach ループで d という文字が表示された後、ループは終了します。 Windows PowerShell のコマンド プロンプトでコマンドとして実行するには、Foreach ステートメント 全体を 1 行で入力する必要があります。代わりに .ps1 スクリプト ファイルにコマンドを記述する場合は、 Foreach ステートメント全体を 1 行で入力する必要はありません。 Foreach ステートメントは、項目のコレクションを返すコマンドレットと共に使用することもで きます。次の例の Foreach ステートメントでは、Get-ChildItem コマンドレットから返された項 目が 1 つずつ順番に処理されます。 foreach ($file in Get-ChildItem) { Write-Host $file } If ステートメントを使用してこの例を改良すると、返される結果を制限できます。次の例の Foreach ステートメントでは、前の例と同じループ処理が実行されますが、If ステートメントを追 加して 100 KB を超えるファイルのみに結果を限定しています。 foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file } } この例では、Foreach ループで $file 変数のプロパティを使用して、比較操作 ($file.length - gt 100k) を実行しています。$file 変数には、Get-ChildItem コマンドレットから返されたオ ブジェクトのすべてのプロパティが格納されます。そのため、ファイル名以外の情報も返すことがで きます。次の例のステートメント リストの中では、サイズと最終アクセス時刻が返されています。 foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file Write-Host $file.length Write-Host $file.lastaccesstime } } この例では、ステートメント リスト内で実行できるコマンドは 1 つに制限されていません。 変数を Foreach ループの外側で使用することも、Foreach ループの内側でインクリメントする こともできます。次の例では、100 KB を超えるファイルがカウントされます。 $i = 0 foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file "file size:" ($file.length / 1024).ToString("F0") KB $i = $i + 1 } } if ($i -ne 0) { Write-Host Write-Host $i " file(s) over 100 KB in the current directory."} else { Write-Host "No files greater than 100 KB in the current directory." } 上の例では、ループの外側で $i 変数が 0 に設定され、100 KB を超えるサイズのファイルが見つ かるたびにループの内側でインクリメントされています。ループが終了すると、If ステートメント で $i の値が評価され、100 KB を超えるファイルの総数が表示されます。または、100 KB を超える ファイルが見つからなかったことを示すメッセージが表示されます。 上の例には、ファイル サイズの結果を書式設定する方法も示されています。 ($file.length / 1024).ToString("F0") 結果をバイト単位ではなく KB 単位で表示するために、値が 1,024 で除算されています。さら に、固定小数点形式指定子を使用して、小数値が結果から削除されるように書式設定されています。 0 は、小数が表示されないように、形式指定子に指示するための指定です。 コマンド パイプライン内の Foreach ステートメント Windows PowerShell では、コマンド パイプライン内に Foreach が現れると、ForEach-Object コマンドを呼び出す foreach エイリアスが使用されます。コマンド パイプライン内で foreach エイリアスを使用するときは、Foreach ステートメントを使用するときのような ($<item> in $<collection>) の構文を含めません。これは、パイプライン内の前のコマンドがこの 情報を提供するためです。コマンド パイプラインで foreach エイリアスを使用するときの構文は次の とおりです。 <command> | foreach {<command_block>} たとえば、次のコマンド パイプライン内の Foreach ループでは、作業セット (メモリ使用量) が 20 MB を超えるプロセスが表示されます。Get-Process コマンドの出力が foreach エイリアスに パイプされています。foreach エイリアスのコマンド ブロックの内部では、Get-Process コマンド レットから渡された WS (作業セット) プロパティの値が $_.WS 変数に格納されます (宣言の $_ の部分は Windows スクリプト ホスト (WSH) 自動変数で、WS の部分がプロパティです)。 If ステートメントでは、条件ステートメントを使用して、作業セットが 20 MB (20,000,000 バイト) を超えるかどうかが判断されます。大きい場合は、$_.name 変数に保存されているプロセスの名前と作業 セットのサイズ (MB 単位) が表示されます。作業セットが 20 MB を超えるプロセスがない場合は、 何も表示されません。 Write-Host "Processes with working-sets greater than 20 MB" Get-Process | foreach { if ($_.WS -gt 20m) { Write-Host $_.name ": " ($_.WS/1m).ToString("F0") MB -Separator "" } } foreach エイリアスでは、最初のコマンド ブロック、中間のコマンド ブロック、および最後のコマンド ブロッ クもサポートされています。最初と最後のコマンド ブロックは 1 回だけ実行され、中間のコマンド ブロックは Foreach ループがコレクションまたは配列を 1 つずつ順に処理するたびに実行されます。 最初、中間、および最後の各コマンド ブロックを指定して、foreach エイリアスをコマンド パイプライン内で 使用するときの構文は次のとおりです。 <command> | foreach {<beginning command_block>}{<middle command_block>}{<ending command_block>} 次の例は、最初、中間、および最後のコマンド ブロックの使用方法を示しています。 Get-ChildItem | foreach { $fileCount = $directoryCount = 0}{ if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{ "$directoryCount directories and $fileCount files"} 最初のコマンド ブロックによって、2 つの変数が作成され、0 に初期化されます。 {$fileCount = $directoryCount = 0} 中間のコマンド ブロックによって、Get-ChildItem から返された各項目がディレクトリかファ イルかが評価されます。 {if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}} 返された項目がディレクトリの場合は、$directoryCount 変数の値が 1 ずつインクリメントさ れ、項目がディレクトリでない場合は、$fileCount 変数の値が 1 ずつインクリメントされます。最 後のコマンド ブロックが、中間のコマンド ブロックのループ処理が完了した後に実行され、処理 の結果が返されます。 {"$directoryCount directories and $fileCount files"} 最初、中間、および最後のコマンド ブロックの構造とパイプライン演算子を使用すると、 サイズが 100 KB を超えるファイルを見つける方法を示していた以前の例を、次のように書き直すことができます。 Get-ChildItem | foreach{ $i = 0}{ if ($_.length -gt 100k) { Write-Host $_.name "file size:" ($_.length / 1024).ToString("F0") KB $i++ } }{ if ($i -ne 0) { Write-Host Write-Host "$i file(s) over 100 KB in the current directory." } else { Write-Host "No files greater than 100 KB in the current directory."} } 関連項目 about_Automatic_Variables about_If Foreach-Object