こんにちは。チェシャ男です。(-皿-)
今回は、ForEach-Object について概要から使用例について簡単にご紹介します。
「コマンドレットリファレンス」カテゴリの記事では省略している情報を参照したい場合に本記事をご覧ください。
もくじ
はじめに
本記事は英語のリファレンス情報しかないコマンドレットについて「Get-Help」等の情報を参考に検証した結果を掲載しています。公式見解ではないことにご注意ください。
正式なヘルプを参照したい場合は、「Get-help ForEach-Object -online」を実行し公式ヘルプをご覧ください。
また、本記事内の例は動作を確認していますが、動作を確約しているわけではありません。
ForEach-Object の概要
ForEach-Object では、入力オブジェクト内に含まれる各要素に対してループ(繰り返し)操作を実行します。
[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/object/foreach-object/”]基本構文
#パターン① ForEach-Object [-Process] <ScriptBlock[]> [-Begin <ScriptBlock>] [-Confirm] [-End <ScriptBlock>] [-InputObject <PSObject>] [-RemainingScripts <ScriptBlock[]>] [-WhatIf] [<CommonParameters>] #パターン② ForEach-Object [-MemberName] <String> [-ArgumentList <Object[]>] [-Confirm] [-InputObject <PSObject>] [-WhatIf] [<CommonParameters>]
[] で囲まれたパラメーターは任意のオプションです。
{}で囲まれた箇所は要素を選択してください。
<>で囲まれた箇所はオブジェクトの型名を示しています。
動作の説明
ForEach-Object コマンドレットは、入力オブジェクト内の各アイテム・要素に対する操作を繰り返し実行します。入力値はパイプライン”|”でコマンドレットに渡すか、”-InputObject” オプションを使用して指定します。
PowerShell 3.0 以降では、ForEach-Object コマンドレットを使用する方法が2つあります。
1つ目は、PowerShell 2.0でも使用できる“{}(スクリプトブロック)”を使った方法です。スクリプトブロックを使用して繰り返し実行する操作を指定します。
スクリプトブロック内では、”$_”変数をループ中のオブジェクトを参照することが可能です。このスクリプトブロックは、”-Process” オプションに指定します。
2つ目は、ステートメント操作を使用する方法です。この手法は PowerShell 3.0 で実装されました。ループ対象に対してプロパティ値の参照を行ったりメソッドを呼び出したりすることができます。
また、スクリプトブロックを使用する手法では主処理の前後の処理を指定するためのオプションが提供されています。Begin オプションの値である Begin スクリプトブロックでは入力オブジェクトの最初の処理前に実行する内容を、Endオプションの値であるEndスクリプトブロックでは最後の処理後に実行する内容を指定できます。
各パラメータについて
-Begin <ScriptBlock>
入力オブジェクトが処理される前に実行される処理内容をスクリプトブロックで指定します。
-Process <ScriptBlock[]>
入力オブジェクトの各要素に対して繰り返し実行される操作を指定します。 操作内容はスクリプトブロック内に記述します。
-End <ScriptBlock>
オブジェクトの処理後に実行される処理内容をスクリプトブロックで指定します。
-InputObject <PSObject>
入力オブジェクトを指定します。 ForEach-Objectは、入力オブジェクト内の各要素に対してスクリプトブロックまたは操作文を適用します。入力オブジェクトには「変数」「コマンドレット」「式」などを指定できます。
-MemberName <String>
参照するプロパティまたは呼び出すメソッドを指定します。PowerShell 3.0で導入されました。
参照するメンバーはGet-Memberコマンドレットで確認することができます。
ワイルドカード文字は使用できますが、指定したメンバーが一意の値である場合にのみ動作します。
-ArgumentList <Object[]>
メソッド呼び出しの引数の配列を指定します。PowerShell 3.0で導入されました。
-RemainingScripts <ScriptBlock[]>
オプション(パラメータ)が指定されていない全てのスクリプトブロックを受け取ります。PowerShell 3.0で導入されました。
-Confirm [<SwitchParameter>]
コマンドレットを実行する前に確認を求めるプロンプトが表示されます。
-WhatIf [<SwitchParameter>]
このスイッチオプションを指定すると実際には実行されず、コマンドレットが実行された場合の動作を確認することができます。
<CommonParameters>
このコマンドレットでは、
Verbose、Debug、ErrorAction、ErrorVariable、WarningAction、WarningVariable、OutBuffer、PipelineVariable、OutVariable
の各共通パラメーターを使用することができます。
入力値
System.Management.Automation.PSObject
(任意のオブジェクトを入力値として指定することができます。)
出力値
System.Management.Automation.PSObject
(入力によって渡されたオブジェクトを返します。)
備考
ForEach-Object コマンドレットは Foreach ステートメントによく似ていますが、Foreach ステートメントではパイプラインから入力値を受け取ることができません。
使用例
例1:配列内の整数を除算する
PS C:\> 1024, 2048, 10240 | ForEach-Object -Process {$_ / 1024} 1 2 10
この例では3つの整数を配列(オブジェクトの)として受け取り、それぞれの整数を1024で割っています。
例2:ディレクトリ内のファイルのサイズを全て取得する
PS C:\> $PSHOME C:\Windows\System32\WindowsPowerShell\v1.0 PS C:\>Get-ChildItem $PSHOME | ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }} Certificate.format.ps1xml 12.5244140625 Diagnostics.Format.ps1xml 4.955078125 DotNetTypes.format.ps1xml 134.9833984375 Event.Format.ps1xml 9.90625 FileSystem.format.ps1xml 24.927734375 getevent.types.ps1xml 8.94921875 Help.format.ps1xml 272.44140625 16.208984375 ====略=
この例では、PowerShell のインストールディレクトリ($PSHOME)内のファイルとディレクトリ(フォルダ)を取得し ForEach-Object コマンドレットに渡しています。
対象がディレクトリでない場合、ファイル名を取得し、Length プロパティ(ファイルサイズ)の値を1024で割り、次の要素と区切るための空行をスペース(” “)で表示しています。
対象がディレクトリであるかどうかは、「PSISContainer」プロパティを使用して判断してます。
例3:システムイベントを操作する
PS C:\>$Events = Get-EventLog -LogName System -Newest 1000 PS C:\>$Events | ForEach-Object -Begin {Get-Date} -Process {Out-File -Filepath Events.txt -Append -InputObject $_.Message} -End {Get-Date}
この例ではシステムのイベントログから最新の1000件のイベントを取得し、$Events変数に格納してます。 その後、イベントを格納した変数を ForEach-Object コマンドレットにパイプで渡しています。
Begin オプションでは開始時の日付と時刻を表示しています。
次に、Process オプションで、Out-Fileコマンドレットを使用して events.txt という名前のテキストファイルを作成し、各イベントのメッセージ( プロパティ)をファイルに書き込んでいます。
最後に、End オプションでは全ての処理が完了した後の日時を表示しています。
例4:$Null自動変数を使用する
PS C:\>1, 2, $null, 4 | ForEach-Object {"Hello"} Hello Hello Hello Hello
この例では ForEach-Object コマンドレットに $Null自動変数をパイプで渡した場合の効果を確認しています。
PowerShell は null (ヌル)をプレースホルダとして処理する(仮置き状態で処理する)ため、ForEach-Object コマンドレットは他のオブジェクトと同様に$Nullの値を使用します。
例5:プロパティ値を取得する
PS C:\>Get-Module -List | ForEach-Object -MemberName Path C:\Program Files\WindowsPowerShell\Modules\PackageManagement\1.0.0.1\PackageManagement.psd1 C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PowerShellGet.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\AppLocker\AppLocker.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\CimCmdlets\CimCmdlets.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ISE\ISE.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psd1 =======略= PS C:\>Get-Module -List | Foreach Path C:\Program Files\WindowsPowerShell\Modules\PackageManagement\1.0.0.1\PackageManagement.psd1 C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PowerShellGet.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\AppLocker\AppLocker.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\CimCmdlets\CimCmdlets.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ISE\ISE.psd1 C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psd1 =======略=
この例では、インストールされている PowerShell モジュールを取得し、Path プロパティの値を参照しています。”-MemberName” オプションを使用して取得したモジュール一覧のオブジェクトから Pathプ ロパティを参照しています。
また、2番目の例ではF orEach-Object コマンドレットのエイリアス「Foreach」を使用し、オプションの “-MemberName” を省略した場合を実行しています。
例6:各パターンでモジュール名をコンポーネント名に分割する
PS C:\>"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object {$_.Split(".")} Microsoft PowerShell Core Microsoft PowerShell Host PS C:\>"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object -MemberName Split -ArgumentList "." Microsoft PowerShell Core Microsoft PowerShell Host PS C:\>"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | Foreach Split "." Microsoft PowerShell Core Microsoft PowerShell Host
この例では、2つの「ドット区切りモジュール名」をコンポーネント名で分割しています。構文の中で文字列を区切る「Split メソッド」を呼び出しています。
3つのコマンドレット実行例では異なる構文を使用していますが処理内容は同じです。
最初の例は、スクリプトブロック内で$_変数を含むドット構文で「Split メソッド」を呼び出してループ中の現在のオブジェクトを区切っています。
2番目の例では、”-MemberName” オプションを使用して「Splitメソッド」を、”-ArgumentName” オプションを指定して区切り文字としてのドット(“.”)を指定しています。
3番目のコマンドは、Foreach-Objectコマンドレットのエイリアス「Foreach」を使用し、オプションの “-MemberName” と “-ArgumentList” を省略しています。