プログラミング学習サイト

プログラミングの学習を開始される方を対象としたプログラミング入門サイトです。

Powershellでのパイプとは何か

Powershell概要

minegishirei.hatenablog.com

パイプラインとは

そもそもパイプラインとは、以下のように「|」記号でコマンドを繋ぐことで、データの変更を可能にする仕組みである。

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:そもそもパイプラインとは、以下のように「|」記号でコマンドを繋ぐことで、データの変更を可能にする仕組みである。

img:https://cdn.slidesharecdn.com/ss_thumbnails/windows-powershell-cookbook-the-complete-guide-to-scripting-microsofts-command-shell-190312151315-thumbnail-4.jpg?cb=1552403608

category_script:page_name.startswith("1")

page:https://minegishirei.hatenablog.com/entry/2024/05/21/120234