05. パイプラインとオブジェクト

本資料の山場 — Get-Member ひとつで、知らないコマンドも自力で扱えるようになる

📅 作成: 2026-08-22 / 更新: 2026-08-23 / 対象: Windows PowerShell 5.1 + PowerShell 7

この章で何ができるようになるか

ここが本資料でもっとも重要な章です。
04 章までは他の言語にもある話でした。この章の内容はPowerShell 固有で、しかもここを理解すると以降が独学できるようになります。逆にここを飛ばすと、ずっと「コマンドを暗記する」学び方から抜け出せません。時間をかける価値があります。

05.1 表示とデータは別物

01 章の復習 — パイプを流れるのはオブジェクト

01 章で見たとおり、Bash のパイプにはテキスト行が、PowerShell のパイプにはオブジェクトが流れます。ここではそれを実際に確かめます。

Get-Process | Select-Object -First 1

実行すると、次のような表が出ます。

 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     28    18.42      35.66       1.42    9876   1 pwsh

ここが最初の落とし穴

この表を見て「7つの項目を持つデータが返ってきた」と考えると間違いです。実際に返ってきているのは System.Diagnostics.Process というオブジェクトで、プロパティは 100 個近くあります

実際のオブジェクト System.Diagnostics.Process Id ProcessName CPU WorkingSet Path StartTime Threads Handle MainWindowTitle Company … プロパティは 100 個近い 整形 画面に出る表示(ビュー) NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName 28 18.42 35.66 1.42 9876 1 pwsh 7 項目だけが選ばれている 見やすさのために PowerShell が決めた既定の見せ方 パイプの次に渡るのは「左の箱」であって「右の表」ではない 表に出ていない Path や StartTime も、次のコマンドからは普通に使える 「表示されていない = 存在しない」ではない。ここを取り違えると調べ方を間違える
図 05.1 — 表示は整形結果にすぎない。パイプに流れるのは元のオブジェクトそのもの

表に出ていない Path も、そのまま使えます。

Get-Process | Select-Object -First 1 | Select-Object Name, Path, StartTime
Bash との決定的な違いはここです。
Bash では ps aux の出力に無い情報は本当に存在しません。欲しければオプションを足して再実行するしかありません。
PowerShell では表示が絞られているだけで、データは全部そこにあります。だから「もう一度実行し直す」のではなく「取り出し方を変える」のが正しい対処になります。

Format-* は最後にだけ使う 重要な罠

Format-TableFormat-List を途中に挟むと、そこでオブジェクトが「表示用の部品」に変換されてしまいます。以降のコマンドはまともに動きません。

# ✗ 動かない — Format-Table の後は表示部品になっている
Get-Process | Format-Table Name, Id | Where-Object { $_.Id -gt 1000 }

# ✓ 絞ってから最後に整形する
Get-Process | Where-Object { $_.Id -gt 1000 } | Format-Table Name, Id
覚え方は「Format は行き止まり」です。
Format-* を書いたら、そのパイプラインはそこで終わりです。ファイルに出す(Export-Csv)、変数に入れる、別のコマンドに渡す — どれもできなくなります。画面で見るための最後の一手と考えてください。
PowerShell が初めての人へ
「オブジェクト」という言葉が難しければ、「名前の付いた項目をまとめて持ち歩ける箱」と考えてください。JavaScript のオブジェクト、Java のインスタンス、VBA のオブジェクト変数と同じものです。
重要なのは、その箱がコマンドからコマンドへそのまま渡されること。文字列に潰れないので、受け取った側は .Id.Path と書くだけで中身を取り出せます。

05.2 Get-Member — 自習の起点

この1つを覚えれば独学できる

05.1 で「表示に出ていない情報がある」と分かりました。ではどうやって中身を知るのか。その答えが Get-Member です。

Get-Process | Get-Member
   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Kill                       Method         void Kill()
Refresh                    Method         void Refresh()
Id                         Property       int Id {get;}
ProcessName                Property       string ProcessName {get;}
StartTime                  Property       datetime StartTime {get;}
CPU                        ScriptProperty System.Object CPU {get=...}
...
| Get-Member ① 型名 System.Diagnostics.Process → この名前で検索できる ② プロパティ Id / Path / StartTime … → 取り出せる値の一覧 ③ メソッド Kill() / Refresh() … → 実行できる操作の一覧 「このコマンドの結果から何が取れるのか」に、その場で答えが出る
図 05.2 — Get-Member は型名・プロパティ・メソッドの3つを一度に教えてくれる

出力の読み方

MemberType意味使い方
Property元の .NET オブジェクトが持つ値$p.Id
NotePropertyPowerShell が後から足した値$p.PSPath
ScriptPropertyアクセス時に計算される値$p.CPU
AliasProperty別名。実体は他のプロパティ$p.Name(実体は ProcessName)
Method実行できる操作$p.Kill()

プロパティだけ見たいとき

Get-Process | Get-Member -MemberType Property

# 短縮形(gm は Get-Member のエイリアス)
Get-Process | gm -MemberType Property

実際の型を確認しておく

コマンド返るオブジェクトの型
Get-ProcessSystem.Diagnostics.Process
Get-ChildItem(ファイル)System.IO.FileInfo
Get-ChildItem(フォルダ)System.IO.DirectoryInfo
Get-ContentSystem.String
Import-CsvSystem.Management.Automation.PSCustomObject
型名が分かると、検索の質が一気に上がります。
「PowerShell ファイル サイズ 取得」で検索するより、「System.IO.FileInfo プロパティ」で検索するほうが確実です。前者は玉石混交の記事が並びますが、後者は Microsoft の公式ドキュメントに直行できます。
PowerShell のオブジェクトは .NET のクラスそのものなので、C# 向けのドキュメントがそのまま使えます。

まず Get-Member、が習慣になれば独学できる

# 知らないコマンドに出会ったとき
Get-Service | Get-Member          # 何が返るか調べる
Get-Service | Select-Object -First 1 | Format-List *   # 実際の値を全部見る

Format-List *すべてのプロパティを実際の値付きで表示します。Get-Member が「何があるか」なら、Format-List * は「いま何が入っているか」です。2つを組み合わせると、未知のコマンドでもすぐ扱えます。

PowerShell が初めての人へ
Java・C# の経験がある方へGet-Member はリフレクション(getClass().getMethods()GetType().GetProperties())を対話的に実行しているようなものです。IDE の補完で見ていた情報を、シェルの中で直接引ける、と考えると分かりやすいはずです。
VBA の経験がある方へ — オブジェクトブラウザ(F2)に相当します。違いは、実際に返ってきた値そのものに対して問い合わせる点です。

05.3 絞る・変える・選ぶ

役割分担を先に押さえる

Where-Object 絞る 件数が減る。中身は変わらない ForEach-Object 変える 1件ずつ処理する。何を返すかは自由 Select-Object 選ぶ 必要なプロパティだけ残す JavaScript の配列メソッドとの対応 .filter() .map() 分割代入に近い ForEach-Object と Select-Object は役割が重なる。プロパティを選ぶだけなら Select-Object が読みやすい
図 05.3 — 3つの使い分け。まず「絞る」を先に書くとパイプライン全体が速くなる

Where-Object — 絞る

# JavaScript
files.filter(f => f.size > 1024)

# PowerShell(スクリプトブロック)
Get-ChildItem | Where-Object { $_.Length -gt 1024 }

# PowerShell(簡易構文 — 比較1つだけならこちらが読みやすい)
Get-ChildItem | Where-Object Length -gt 1024

$_いま流れてきた1件を指す自動変数です。$PSItem とも書けますが、$_ のほうが一般的です。

書き方使いどころ
スクリプトブロックWhere-Object { $_.Length -gt 1024 }複数条件、複雑な式
簡易構文Where-Object Length -gt 1024比較1つだけ。読みやすい
エイリアス? { $_.Length -gt 1024 }対話操作のみ。スクリプトでは使わない

ForEach-Object — 変える

# JavaScript
files.map(f => f.name.toUpperCase())

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

3つのブロックを持てる

1..3 | ForEach-Object -Begin { "開始" } -Process { $_ * 10 } -End { "終了" }
# → 開始 / 10 / 20 / 30 / 終了

-Begin は最初に1回、-End は最後に1回だけ実行されます。集計の初期化と結果出力に使えます。

並列実行 pwsh 7

1..10 | ForEach-Object -Parallel { Start-Sleep 1; $_ } -ThrottleLimit 5
-Parallel の中は別のセッションです。
外側の変数はそのままでは見えません。使いたい場合は $using: を付けます($using:baseDir)。また、1件あたりの処理が軽いと並列化のオーバーヘッドのほうが大きくなります。ネットワーク待ちなど、待ち時間が長い処理にだけ使ってください。

Select-Object — 選ぶ

Get-Process | Select-Object Name, Id, CPU
Get-Process | Select-Object -First 5
Get-Process | Select-Object -Property Name -Unique

-ExpandProperty — 値そのものを取り出す よく使う

# オブジェクトが返る(Name というプロパティを持つ箱)
Get-Process | Select-Object -First 1 -Property Name
# → @{Name=pwsh}

# 値そのものが返る(ただの文字列)
Get-Process | Select-Object -First 1 -ExpandProperty Name
# → pwsh
「なぜか文字列にならない」の原因はたいていこれです。
Select-Object NameName というプロパティを1つだけ持つ新しいオブジェクトを作ります。文字列そのものが欲しいときは -ExpandProperty を使うか、ForEach-Object { $_.Name } と書きます。

計算プロパティ — 列を作る

Get-ChildItem | Select-Object Name, @{ Name = 'MB'; Expression = { [math]::Round($_.Length / 1MB, 2) } }

Name(列名)と Expression(値の計算式)のハッシュテーブルを渡すと、その場で新しい列を作れますN / E と略記もできます。

Select-Object を通すと型が変わります。
元が FileInfo でも、Select-Object Name, Length を通した後は PSCustomObject になります。.Delete() のようなメソッドは呼べなくなります
ファイル操作を続けたいなら、絞るだけにして Select-Object は最後に置いてください。
PowerShell が初めての人へ
$_「いま処理している1件」を表します。JavaScript の arr.filter(x => ...)x にあたるものが、名前を書かずに $_ として用意されている、と考えてください。
入れ子にすると内側の $_ が外側を隠してしまうので、ネストするときは ForEach-Object { $item = $_; ... } のように名前を付けて退避させます。

05.4 並べる・まとめる・数える

集計の3兄弟

Sort-Object 並べる 件数は変わらない Group-Object まとめる Name / Count / Group を返す Measure-Object 数える 合計・平均・最大 実例 — プロジェクト内のファイルを拡張子別に数える Get-ChildItem -Recurse -File | Group-Object Extension | Sort-Object Count -Descending .png 82 件 .html 5 件 .json 5 件 Bash なら awk と sort と uniq -c を組み合わせる場面が、コマンド2つで済む
図 05.4 — 集計は「並べる → まとめる → 数える」の組み合わせで書ける

Sort-Object — 並べる

Get-ChildItem | Sort-Object Length -Descending
Get-ChildItem | Sort-Object Extension, Name          # 複数キー
Get-Process   | Sort-Object CPU -Descending -Top 5   # 上位だけ

Group-Object — まとめる

返るのは GroupInfo というオブジェクトで、3つのプロパティを持ちます。

プロパティ中身
Nameグループのキー(例: .png
Countそのグループの件数
Groupグループに属する元のオブジェクトすべて
# 拡張子ごとの合計サイズを出す
Get-ChildItem -Recurse -File |
    Group-Object Extension |
    ForEach-Object {
        [PSCustomObject]@{
            拡張子 = $_.Name
            件数   = $_.Count
            合計MB = [math]::Round(($_.Group | Measure-Object Length -Sum).Sum / 1MB, 2)
        }
    } | Sort-Object 合計MB -Descending

$_.Group に元のファイルオブジェクトが全部入っているので、そこからさらに集計できます

グループ化しても元データは失われません。
SQL の GROUP BY では集計関数を通した値しか取れませんが、Group-Object元のオブジェクトを Group に丸ごと保持します。後から「やっぱり平均も欲しい」となっても、再実行せずに取り出せます。

Measure-Object — 数える

Get-ChildItem | Measure-Object                                    # 件数だけ
Get-ChildItem | Measure-Object Length -Sum -Average -Maximum      # 集計
Count    : 4
Average  : 43403.5
Sum      : 173614
Maximum  : 48259
Property : Length
件数を数えるだけなら .Count で十分です。
(Get-ChildItem).Count のほうが短く、速く書けます。Measure-Object が要るのは合計・平均・最大最小を同時に取りたいときです。
ただし .Count全件をメモリに載せてから数えます。数十万件を扱うなら Measure-Object のほうが安全です。

組み合わせの実例

# 直近7日に更新された .ps1 を、サイズの大きい順に5件
Get-ChildItem -Recurse -Filter *.ps1 |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
    Sort-Object Length -Descending |
    Select-Object -First 5 Name, Length, LastWriteTime |
    Format-Table -AutoSize

絞る → 並べる → 選ぶ → 整形するの順です。Format-Table が最後に来ていることに注目してください(05.1 の罠)。

PowerShell が初めての人へ
パイプラインは行末で改行できます| で終わっている行は「まだ続く」と解釈されるので、上の例のように1行1コマンドで縦に並べると読みやすくなります。
長いパイプラインを1行に詰め込む必要はありません。スクリプトに書くときは必ず改行して並べてください。

05.5 コマンドの探し方

すべてのコマンドは「動詞-名詞」

Get - Process 動詞 — 何をするか 名詞 — 何に対して Get / Set / New / Remove / Start … Process / Service / Item / Content … 動詞は 100 個に決められている Get 取得 / Set 設定 / New 作成 Remove 削除 / Start 開始 / Stop 停止 Get-Verb で全部見られる だから名前から機能が推測できる サービスを止めたい → Stop-Service ファイルを作りたい → New-Item 暗記ではなく「組み立てて」探せる
図 05.5 — 動詞は承認された 100 個に統一されている。だから名前が推測できる
Get-Verb | Measure-Object      # → Count: 100
Get-Verb | Where-Object Group -eq 'Common'

Get-Command で探す

Get-Command -Verb Get -Noun Process        # 動詞と名詞で絞る
Get-Command *service*                      # 名前の一部で探す
Get-Command -Module Microsoft.PowerShell.Management

Get-Help で使い方を見る

Get-Help Get-ChildItem                     # 概要
Get-Help Get-ChildItem -Examples           # 使用例だけ(最も実用的)
Get-Help Get-ChildItem -Full               # 全部
Get-Help Get-ChildItem -Online             # ブラウザで公式ドキュメント
まず -Examples を見る癖をつけてください。
パラメータの一覧を読むより、動く例を1つ見るほうが速いことがほとんどです。ヘルプが入っていない場合は Update-Help で取得できます(管理者権限が必要)。

未知のコマンドを扱う4ステップ

① 探す Get-Command 名前を組み立てる ② 使い方を見る Get-Help -Examples 動く例を1つ得る ③ 動かす まず1件だけ -First 1 で試す ④ 中身を見る Get-Member 取り出せる値を知る この4ステップが回せれば、資料に載っていないコマンドも自力で使える 検索してコピペするより速く、しかも確実に自分の環境で動く答えが得られる
図 05.6 — 未知のコマンドに出会ったときの手順。暗記ではなく調べ方を身につける

省略形は3種類ある

ls のような短縮表記には仕組みの異なる3種類があります。混同すると「一覧はどこにあるのか」が分からなくなります。

種類一覧を出せるか
コマンドのエイリアスls → Get-ChildItemできるGet-Alias
パラメータのエイリアス-Recurse の別名が -s / -rできるコマンドごとに調べる
パラメータの前方一致-Rec → -Recurseできないその場で解決される

① コマンドのエイリアス — Get-Alias で一覧できる

Get-Alias                                # 全部見る
Get-Alias ls                             # ls の正体を調べる
Get-Alias -Definition Get-ChildItem      # 逆引き → dir, gci, ls の3つ
Get-Help about_Aliases                   # 公式の解説

初期値は PowerShell 本体に組み込まれています。設定ファイルに書かれているわけではないので、Get-Alias が唯一の確実な一覧です。

環境初期のエイリアス数
5.1 Windows PowerShell約 153 個
pwsh 7 PowerShell 7約 135 個
数は固定ではありません。
Get-AliasSource 列を見ると出どころが分かります。ほとんどはエンジン組み込みですが、モジュールを読み込むと増えます。「一覧を控えておく」のではなく、必要になったらその場で Get-Alias を叩くのが正しい使い方です。

5.1 と 7 で中身が違う 実害あり

7 では 19 個のエイリアスが削除されました。特に次の2つは挙動が変わります。

別名5.1 での正体pwsh 7削除の理由
curlInvoke-WebRequest本物の curl.exe が動く実在のコマンドを隠していた
scSet-Content本物の sc.exe が動く同上(サービス制御コマンド)
gwmiGet-WmiObject存在しないコマンド自体が 7 で削除(03 章)
curl と書いたスクリプトは、5.1 と 7 で全く違う動作をします。
5.1 では PowerShell の Invoke-WebRequest が、7 では Windows 同梱の curl.exe が動きます。引数の書き方が全く違うため、移植したとたんに動かなくなります。これがエイリアスを避けるべき最も具体的な理由です。

② パラメータのエイリアス — コマンドごとに調べる

(Get-Command Get-ChildItem).Parameters['Recurse'].Aliases
# → s, r

(Get-Command Get-ChildItem).Parameters['LiteralPath'].Aliases
# → PSPath, LP

これは正式に定義された別名なので、前方一致とは違って安定しています。とはいえ読み手に伝わりにくいため、スクリプトでは正式名を使います。

③ パラメータの前方一致 — 一覧が存在しない 危険

パラメータ名は他と区別できるところまで縮められます。ただし一覧はなく、何に解決されるかが状況で変わります

Get-ChildItem -Rec       # → Recurse に解決される  ✓
Get-ChildItem -Fil       # → Filter に解決される   ✓
Get-ChildItem -F         # → エラー
# Parameter cannot be processed because the parameter name 'F' is ambiguous.
# Possible matches include: -Filter -Force.
あいまいエラーの候補に -File が出てこない点に注目してください。
Get-ChildItem には -File-Filter もあるのに、-Fi-Filter に解決されます-File は FileSystem プロバイダの動的パラメータで、-Filter はコマンド自身の静的パラメータのため、扱いが異なるからです。
どちらに解決されるかを予測するのは現実的ではありません。対話操作で使うのは構いませんが、スクリプトには必ずフルネームを書いてください。

結論 — 対話は自由、ファイルは正式名

よく使う別名正式名
ls / dir / gciGet-ChildItem
cat / type / gcGet-Content
%ForEach-Object
?Where-Object
selectSelect-Object
gmGet-Member
エイリアスは各人が上書きできます。
プロファイル(03 章)で Set-Alias を書けば ls の意味を変えられます。つまり配布したスクリプトが相手の環境で別の動きをする可能性があります。
バージョン差・上書き・前方一致の3つが重なるため、ファイルに保存するものは必ず正式名で書く — これを習慣にしてください。対話操作では自由に使って構いません。

この章のまとめ

やりたいことコマンドJavaScript
中身を調べる| Get-Member—(IDE の補完に相当)
実際の値を全部見る| Format-List *console.dir()
絞る| Where-Object.filter()
変える| ForEach-Object.map()
プロパティを選ぶ| Select-Object分割代入
値そのものを取る-ExpandProperty.map(x => x.name)
並べる| Sort-Object.sort()
まとめる| Group-Object.reduce()
数える・集計する| Measure-Object.length / .reduce()
コマンドを探すGet-Command

覚えておく3点

  1. 画面の表示は整形結果にすぎない。パイプに流れるのは元のオブジェクトなので、表に出ていない値もそのまま使える。Format-* は行き止まりなので最後にだけ置く
  2. 迷ったら Get-Member。型名・プロパティ・メソッドが一度に分かる。型名で検索すれば公式ドキュメントに直行できる
  3. コマンド名は「動詞-名詞」で組み立てられる。暗記せず Get-CommandGet-Help -Examples で探す。エイリアスは対話専用
次章の予告 — 06. 制御構文と関数
ここまでで、既存のコマンドを組み合わせて使えるようになりました。次は自分の処理を関数として切り出す段階です。ifforeach は他言語とほぼ同じですが、関数の戻り値の扱いだけは PowerShell 独特で、経験者ほど引っかかります。「return したつもりの値以外も混ざって返ってくる」問題を正面から扱います。