PowerShellを使っていると、1つのコマンドで完結しないケースによく出会います。
「ファイル一覧から特定の名前だけ取り出したい」
「サービス一覧を条件でフィルタしたい」
「プロセスを並び替えて表示したい」
…そんなときに便利なのがパイプライン(|
)です。
UNIX系のシェルに慣れている人にも馴染み深いこの記号ですが、PowerShellのパイプは**「文字列」ではなく「オブジェクト」を渡す**のが最大の特徴です。
この記事では、PowerShellパイプラインの基本構文・実例・応用テクニックまで、初心者にもわかりやすく丁寧に解説します。
PowerShellのパイプラインとは?

パイプライン(|)の基本概念
PowerShellでは、コマンドの出力(結果)を、次のコマンドの入力として渡すためにパイプ|
を使います。
基本的な書き方:
コマンド1 | コマンド2 | コマンド3
例:
Get-Process | Where-Object { $_.CPU -gt 10 } | Sort-Object CPU
この例では、「プロセス一覧を取得」→「CPU使用率10以上でフィルタ」→「CPU使用率で並び替え」という処理が流れるように実行されます。
他のシェルとの最大の違い:オブジェクトを渡す
シェル | パイプで渡すデータ | 特徴 |
---|---|---|
bash/cmd | 文字列(テキスト) | 単純だが加工が必要 |
PowerShell | .NETオブジェクト | 構造化されたデータをそのまま利用 |
具体例で理解しよう:
bashの場合(文字列処理):
ps aux | grep "firefox" | awk '{print $2}'
PowerShellの場合(オブジェクト処理):
Get-Process firefox | Select-Object Id
PowerShellでは、プロセスオブジェクトのId
プロパティに直接アクセスできるため、より直感的で確実な処理が可能です。
オブジェクトの構造を理解しよう
プロセスオブジェクトの例:
# プロセス情報を取得
$process = Get-Process notepad
# オブジェクトのプロパティを確認
$process | Get-Member
出力例:
Name MemberType Definition
---- ---------- ----------
Id Property int Id {get;}
ProcessName Property string ProcessName {get;}
CPU Property double CPU {get;}
WorkingSet Property long WorkingSet {get;}
...
これらのプロパティに、パイプライン内で直接アクセスできるのがPowerShellの強みです。
ポイント: PowerShellのパイプラインは、構造化されたデータをそのまま受け渡しできるため、より強力で柔軟な処理が可能です。
基本的な使い方とパターン別実例

① Where-Object:条件でフィルタリング
基本構文:
コマンド | Where-Object { 条件式 }
# 短縮形
コマンド | ? { 条件式 }
実例1:CPU使用率でプロセスをフィルタ
Get-Process | Where-Object { $_.CPU -gt 10 }
実例2:実行中のサービスのみ表示
Get-Service | Where-Object { $_.Status -eq "Running" }
実例3:特定サイズ以上のファイルを検索
Get-ChildItem C:\Temp | Where-Object { $_.Length -gt 1MB }
実例4:複数条件でのフィルタ
Get-Process | Where-Object { $_.CPU -gt 5 -and $_.WorkingSet -gt 100MB }
② Sort-Object:並び替え
基本構文:
コマンド | Sort-Object プロパティ名
# 降順の場合
コマンド | Sort-Object プロパティ名 -Descending
実例1:CPU使用率で並び替え
Get-Process | Sort-Object CPU -Descending
実例2:ファイルサイズで並び替え
Get-ChildItem | Sort-Object Length -Descending
実例3:複数プロパティで並び替え
Get-Service | Sort-Object Status, Name
③ Select-Object:必要な情報だけ抽出
基本構文:
コマンド | Select-Object プロパティ1, プロパティ2
# 先頭n件のみ
コマンド | Select-Object -First n
実例1:プロセス名とCPU使用率のみ表示
Get-Process | Select-Object ProcessName, CPU
実例2:ファイル名とサイズのみ表示
Get-ChildItem | Select-Object Name, Length
実例3:上位5件のみ取得
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
④ 出力とエクスポート
ファイルに保存:
Get-Process | Where-Object { $_.CPU -gt 5 } | Out-File "highcpu.txt"
CSVファイルに出力:
Get-Service | Export-Csv "services.csv" -NoTypeInformation
グリッド表示(GUI):
Get-Process | Out-GridView
HTML形式で出力:
Get-Service | ConvertTo-Html | Out-File "services.html"
実用的な組み合わせ例
例1:大きなファイルを見つける
Get-ChildItem C:\ -Recurse |
Where-Object { !$_.PSIsContainer -and $_.Length -gt 100MB } |
Sort-Object Length -Descending |
Select-Object FullName, @{Name="SizeMB";Expression={[math]::Round($_.Length/1MB,2)}} |
Format-Table -AutoSize
例2:停止中のサービスを確認
Get-Service |
Where-Object { $_.Status -eq "Stopped" } |
Sort-Object Name |
Select-Object Name, Status |
Export-Csv "stopped_services.csv" -NoTypeInformation
ポイント: 基本的な組み合わせだけでも、フィルタ・抽出・並び替え・出力保存が自在に可能になります。
PowerShellパイプラインの応用テクニック

高度なフィルタリング
正規表現を使ったフィルタ:
Get-Process | Where-Object { $_.ProcessName -match "^s.*" }
# 「s」で始まるプロセス名のみ
配列に含まれるかのチェック:
$criticalServices = @("Spooler", "DHCP", "DNS")
Get-Service | Where-Object { $_.Name -in $criticalServices }
Null値のチェック:
Get-Process | Where-Object { $_.MainWindowTitle -ne "" }
# ウィンドウタイトルがあるプロセスのみ
ForEach-Object:カスタム処理
基本構文:
コマンド | ForEach-Object { カスタム処理 }
# 短縮形
コマンド | % { カスタム処理 }
実例1:各サービスの状態を整形表示
Get-Service | ForEach-Object {
"Service: $($_.Name) is $($_.Status)"
}
実例2:ファイル拡張子を変更
Get-ChildItem *.txt | ForEach-Object {
Rename-Item $_.FullName $_.FullName.Replace(".txt", ".bak")
}
実例3:計算処理を追加
Get-Process | ForEach-Object {
[PSCustomObject]@{
Name = $_.ProcessName
"MemoryMB" = [math]::Round($_.WorkingSet / 1MB, 2)
"CPUPercent" = [math]::Round($_.CPU, 2)
}
}
Measure-Object:統計処理
基本的な統計:
Get-ChildItem | Measure-Object -Property Length -Sum -Average -Maximum
プロセスのメモリ使用量統計:
Get-Process | Measure-Object -Property WorkingSet -Sum -Average |
ForEach-Object {
[PSCustomObject]@{
"総メモリ使用量(GB)" = [math]::Round($_.Sum / 1GB, 2)
"平均メモリ使用量(MB)" = [math]::Round($_.Average / 1MB, 2)
"プロセス数" = $_.Count
}
}
Group-Object:グループ化
サービスの状態別グループ化:
Get-Service | Group-Object Status
ファイルの拡張子別グループ化:
Get-ChildItem | Group-Object Extension |
Sort-Object Count -Descending |
Select-Object Name, Count
プロセスの会社別グループ化:
Get-Process | Group-Object Company |
Where-Object { $_.Name -ne "" } |
Sort-Object Count -Descending |
Select-Object Name, Count -First 10
複雑なチェーン処理の例
システム監視スクリプトの例:
Get-Process |
Where-Object { $_.CPU -gt 5 -or $_.WorkingSet -gt 500MB } |
Sort-Object CPU -Descending |
Select-Object @{Name="プロセス名";Expression={$_.ProcessName}},
@{Name="CPU使用率";Expression={[math]::Round($_.CPU,2)}},
@{Name="メモリ(MB)";Expression={[math]::Round($_.WorkingSet/1MB,2)}},
@{Name="開始時刻";Expression={$_.StartTime}} |
Format-Table -AutoSize |
Out-String |
Add-Content "system_monitor.log"
ディスク使用量レポートの例:
Get-ChildItem C:\ -Recurse -Directory -ErrorAction SilentlyContinue |
ForEach-Object {
$size = (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
[PSCustomObject]@{
Folder = $_.FullName
SizeGB = [math]::Round($size / 1GB, 2)
}
} |
Where-Object { $_.SizeGB -gt 1 } |
Sort-Object SizeGB -Descending |
Export-Csv "disk_usage.csv" -NoTypeInformation
ポイント: Where-Object
、ForEach-Object
、Measure-Object
などと組み合わせることで、複雑な処理も一行で記述できます。
パイプライン利用時の注意点とトラブル対策

よくある問題と対処法
問題① パイプ対象が空で何も起きない
# 存在しないプロセスを検索
Get-Process -Name "NotExistProcess" | Where-Object { $_.CPU -gt 5 }
# → エラーにならないが、何も表示されない
対策:存在確認を事前に行う
if (Get-Process -Name "notepad" -ErrorAction SilentlyContinue) {
Get-Process -Name "notepad" | Where-Object { $_.CPU -gt 5 }
} else {
Write-Host "指定されたプロセスが見つかりません"
}
問題② 出力が多すぎて画面に収まらない
対策1:ページャーを使用
Get-Process | More
対策2:GUI表示を使用
Get-Process | Out-GridView
対策3:件数を制限
Get-Process | Select-Object -First 10
問題③ エラーが発生して処理が止まる
対策:エラー処理を追加
Get-ChildItem C:\ -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt 1GB }
$_(パイプライン変数)の理解
$_
とは:
- パイプラインで渡されるオブジェクト1つを表す特別な変数
Where-Object
やForEach-Object
内で使用
正しい使用例:
Get-Service | Where-Object { $_.Status -eq "Running" }
# ↑ここの$_は各サービスオブジェクト
よくある間違い:
Get-Service | Where-Object { Status -eq "Running" }
# エラー:$_が抜けている
パフォーマンスの考慮
遅い処理の例:
# 大量のファイルを1つずつ処理
Get-ChildItem C:\ -Recurse | ForEach-Object { Test-Path $_.FullName }
改善された処理:
# 条件を先に絞り込む
Get-ChildItem C:\ -Recurse -File | Where-Object { $_.Length -gt 1MB }
デバッグのコツ
段階的にパイプラインを構築:
# ステップ1:基本データを確認
Get-Process
# ステップ2:フィルタを追加
Get-Process | Where-Object { $_.CPU -gt 5 }
# ステップ3:並び替えを追加
Get-Process | Where-Object { $_.CPU -gt 5 } | Sort-Object CPU
# ステップ4:出力形式を調整
Get-Process | Where-Object { $_.CPU -gt 5 } | Sort-Object CPU | Select-Object Name, CPU
中間結果の確認:
Get-Process | Tee-Object -Variable processes | Where-Object { $_.CPU -gt 5 }
# $processes変数で中間結果を確認可能
ポイント: パイプラインは便利ですが、無出力=バグではないことや$_
の扱いに注意が必要です。
実用的なパイプラインスクリプト例
システム管理
メモリ使用量が多いプロセスの監視:
function Monitor-HighMemoryProcesses {
Get-Process |
Where-Object { $_.WorkingSet -gt 100MB } |
Sort-Object WorkingSet -Descending |
Select-Object ProcessName,
@{Name="MemoryMB";Expression={[math]::Round($_.WorkingSet/1MB,2)}},
Id, StartTime |
Format-Table -AutoSize
}
サービスの健全性チェック:
function Check-CriticalServices {
$criticalServices = @("Spooler", "Themes", "AudioSrv")
$criticalServices | ForEach-Object {
$service = Get-Service $_ -ErrorAction SilentlyContinue
if ($service) {
[PSCustomObject]@{
ServiceName = $_
Status = $service.Status
StartType = $service.StartType
IsRunning = ($service.Status -eq "Running")
}
}
} | Format-Table -AutoSize
}
ファイル管理
重複ファイルの検出:
function Find-DuplicateFiles {
param([string]$Path = ".")
Get-ChildItem $Path -Recurse -File |
Group-Object Length |
Where-Object { $_.Count -gt 1 } |
ForEach-Object {
$_.Group | Group-Object {
(Get-FileHash $_.FullName).Hash
} |
Where-Object { $_.Count -gt 1 } |
ForEach-Object {
Write-Host "重複ファイル発見:" -ForegroundColor Yellow
$_.Group | Select-Object FullName, Length | Format-Table
}
}
}
古いファイルのクリーンアップ:
function Remove-OldFiles {
param(
[string]$Path,
[int]$DaysOld = 30
)
$cutoffDate = (Get-Date).AddDays(-$DaysOld)
Get-ChildItem $Path -Recurse -File |
Where-Object { $_.LastWriteTime -lt $cutoffDate } |
ForEach-Object {
Write-Host "削除: $($_.FullName)" -ForegroundColor Red
# Remove-Item $_.FullName -Force # 実際に削除する場合はコメントアウト
}
}
ログ解析
イベントログの分析:
function Analyze-EventLog {
param([int]$Hours = 24)
$startTime = (Get-Date).AddHours(-$Hours)
Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=$startTime} -ErrorAction SilentlyContinue |
Group-Object LevelDisplayName |
Sort-Object Count -Descending |
Select-Object @{Name="レベル";Expression={$_.Name}},
@{Name="件数";Expression={$_.Count}} |
Format-Table -AutoSize
}
よくある質問と回答

Q: パイプラインはどこまで長くできますか?
A: 技術的制限はありませんが、可読性のため適度な長さに
# 読みやすい例(改行で整理)
Get-Process |
Where-Object { $_.CPU -gt 5 } |
Sort-Object CPU -Descending |
Select-Object Name, CPU |
Format-Table -AutoSize
Q: bashのパイプラインとの互換性は?
A: 基本的な構文は似ていますが、データの扱いが異なります
項目 | bash | PowerShell |
---|---|---|
区切り文字 | 改行・スペース | オブジェクトのプロパティ |
データ型 | 文字列のみ | 型付きオブジェクト |
フィルタ | grep | Where-Object |
並び替え | sort | Sort-Object |
Q: パフォーマンスを向上させるには?
A: 以下の点に注意してください
- 早い段階でフィルタ:Where-Objectを最初に配置
- 必要なプロパティのみ選択:Select-Objectで絞り込み
- エラー処理:-ErrorAction SilentlyContinueで継続
- バッチ処理:ForEach-Objectより配列操作を優先
Q: デバッグはどうすれば?
A: 段階的な構築とTee-Objectの活用
# 中間結果を変数に保存
Get-Process | Tee-Object -Variable allProcesses |
Where-Object { $_.CPU -gt 5 } | Tee-Object -Variable filteredProcesses |
Sort-Object CPU
# 後で中間結果を確認
$allProcesses.Count
$filteredProcesses.Count
まとめ:PowerShellのパイプラインで作業をスマートに効率化しよう!
今回学んだ重要なポイント:
- 基本概念:オブジェクトを渡すPowerShell独自の仕組み
- 基本操作:Where-Object、Sort-Object、Select-Objectの組み合わせ
- 応用テクニック:ForEach-Object、Measure-Object、Group-Objectの活用
- 実践的な使い方:システム管理、ファイル管理、ログ解析への応用
実際に使ってみよう:
- 基本的なフィルタリングから始める
- 段階的にパイプラインを構築する練習
- 実用的なスクリプトを作成してみる
- エラー処理とデバッグの方法を覚える
PowerShellのパイプラインは、オブジェクトを受け渡すことで複雑な処理をシンプルに表現できる強力な仕組みです。
- フィルタ:
Where-Object
- 並べ替え:
Sort-Object
- 抽出:
Select-Object
- 出力:
Out-File
、Out-GridView
、Export-Csv
コメント