- Powershell概要
- パイプラインとは
- パイプライン1 コマンドの出力結果のフィルタリング
- Where-Objectについて
- コマンドの出力テーブルのうち、一部を出力したい。
- 停止しているサービス一覧を取得する
- Foreach-Objectについて
- Foreach-Objectの応用
- パイプラインの速度について
Powershell概要
パイプラインとは
そもそもパイプラインとは、以下のように「|」記号でコマンドを繋ぐことで、データの変更を可能にする仕組みである。
Get-Process | Where-Object { $_.WorkingSet -gt 500kb } | Sort-Object -Descending Name
上記の例ならば
#プロセス一覧 | プロセスのWorkingSetが500kb以上を取り出す | 名前の降順で並び替える Get-Process | Where-Object { $_.WorkingSet -gt 500kb } | Sort-Object -Descending Name
というように、あたかも工場の生産ラインのようにデータを変形していくことができる。 この仕組みをパイプラインという
パイプライン1 コマンドの出力結果のフィルタリング
Get-Process | Where-Object { $_.Name -like "*Search*" }
-like演算子はワイルドカードと一致するかどうかを確かめる
上記の例ならばSerachがName文字列に入っているかどうかで次に渡すかどうかを決める。
上のコマンドはプロセス一覧を手に入れた後、名前が「Search」を含んでいるもののみ表示する
Where-Objectについて
Where-Objectはフィルタリングのためのコマンドレットである。
Where-Objectのあとの{}内でスクリプトを実行し、その実行結果がFalse出ないものを変換する
また、Where-Objectは受け渡された全ての行に目を通すが、$_は現在処理している物を表す。(今回の例だと各プロセスのこと)
コマンドの出力テーブルのうち、一部を出力したい。
Get-ChildItem | Where-Object { $_.PsIsContainer }
全てのディレクトリのうちPsIsContainerプロパティを次に受け渡すことで、ディレクトリ一覧を表示できる。
停止しているサービス一覧を取得する
Get-Service | Where-Object { $_.Status -eq "Stopped" }
Foreach-Objectについて
Foreach-Objectは入力を受けた全ての行に対して{}内の処理を行うことができる。
1..10 | Foreach-Object { $_ * 2 }
上記の例では1..10という1から10が格納された配列に対して、各要素が$_に格納されることになり、それぞれを二倍している。
よって出力は以下のようになる
2 4 6 8 10 12 14 16 18 20
Foreach-Objectの応用
全てのメモ帳プロセスの終了を検知する
$notepadProcesses = Get-Process notepad $notepadProcesses | Foreach-Object { $_.WaitForExit() }
Get-Processコマンドでnotepadを指定することで、現在動いている全てのメモ帳プロセスに関するデータを手に入れることができる。
また、手に入れたメモ帳の各プロセスについてForeach-Objectを用いてWaitForExit()を実行する
このWaitForExitメソッドはプロセスが終了されるまで待つという意味である。
これらのプロセス全てが終了するまで、このプログラムは先には進まない
パイプラインの速度について
具体例1
Get-ChildItem C:\ *.txt -Recurse | Out-File c:\temp\AllTextFiles.txt
上のコマンドの方が以下のコマンドより早い
$files = Get-ChildItem C:\ *.txt –Recurse $files | Out-File c:\temp\AllTextFiles.txt
なぜ早いのか
遅い方のコマンドでは$filesに一度全ての実行結果を格納している
その結果、filesにメモリーの容量が奪われ、CPUに負荷を与える(CPUが一度に覚えておかなければいけないことが多くなる)
それに対し、パイプラインはいわゆる「流れ」を形成する。
Get-ChildItemで取得したデータは止まらずにすぐにOutFileで出力されるため、CPUが覚えておかなければならない量が減る
具体例2
$output = New-Object System.Text.StringBuilder Get-ChildItem C:\ *.txt -Recurse | Foreach-Object { [void] $output.Append($_.FullName + "`n") } $output.ToString()
上のコマンドの方が以下のコマンドより早い
$output = "" Get-ChildItem C:\ *.txt -Recurse | Foreach-Object { $output += $_.FullName } $output
参考記事
この記事は以下の書籍を参考に執筆されました。 詳しい内容の確認はこちらからお願いいたします。
title:誰でもわかる!powershell入門学習サイト パイプライン編
description:そもそもパイプラインとは、以下のように「|」記号でコマンドを繋ぐことで、データの変更を可能にする仕組みである。
category_script:page_name.startswith("1")
page:https://minegishirei.hatenablog.com/entry/2024/05/21/120234