在本章中,我們會深入探索管線,並挖掘一些更強大的能力,讓你能以更省力的方式,正確地在各個命令之間傳遞資料。
在 PowerShell 中,commandA | commandB 是透過管道( pipeline )進行資料的傳遞,而這個過程就是「管道參數綁定」( Pipeline Parameter Binding )。這個機制讓前一個指令的輸出自動地傳遞給下一個指令,而不需要額外的變數或參數傳遞,實現自動化處理流程。
管道參數綁定的核心在於 PowerShell 會嘗試將前一個命令的輸出( commandA )與下一個命令的參數( commandB )自動匹配。這個匹配過程主要有兩種方式:
PowerShell 會檢查 commandB 的參數是否可以直接接受 commandA 的輸出類型。如果匹配成功,就直接將資料傳遞給該參數。
以下範例中,Get-Process 輸出的是 System.Diagnostics.Process 物件,Stop-Process 可以接受 Process 類型的物件作為參數,因此它們可以直接按值匹配。
# 取得正在執行的 notepad 進程並停止
Get-Process -Name Telegram | Stop-Process
# 使用 Get-Process 並查看其輸出物件的類型,
PS /Users/kanglin/code/30days> Get-Process Telegram | gm
TypeName: System.Diagnostics.Process
# 查看 Stop-Process 指令的參數資訊,特別是 InputObject
PS /Users/kanglin/code/30days> Get-Help Stop-Process -Parameter InputObject
-InputObject <System.Diagnostics.Process[]>
Specifies the process objects to stop. Enter a variable that contains the objects, or type a command or expression that gets the objects.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByValue)
Accept wildcard characters? false
一般來說,具有相同名詞的命令(如 Get-Process 和 Stop-Process),通常都能夠以 ByValue 方式將資料傳輸給彼此。
如果 commandA 輸出的對象是物件,PowerShell 會檢查物件的屬性名稱是否與 commandB 參數名稱相同。若找到相同的名稱,就將相應的屬性值傳遞給該參數。
以下範例中,Select-Object 用來建立一個包含 Id 和 Name 屬性的自定義物件,然後將其傳遞給 Stop-Process,其中 Id 屬性會匹配到 Stop-Process 的 -Id 參數。
# 建立一個自定義物件,然後使用 Stop-Process 按物件屬性名稱停止進程
$processInfo = Get-Process -Name Telegram | Select-Object Id, Name
$processInfo | Stop-Process
透過 Get-Command 查看參數的詳細資訊
PS /Users/kanglin/code/30days> (Get-Command Stop-Process).Parameters
Key Value
--- -----
Name System.Management.Automation.ParameterMetadata
Id System.Management.Automation.ParameterMetadata
InputObject System.Management.Automation.ParameterMetadata
PassThru System.Management.Automation.ParameterMetadata
Force System.Management.Automation.ParameterMetadata
Verbose System.Management.Automation.ParameterMetadata
Debug System.Management.Automation.ParameterMetadata
ErrorAction System.Management.Automation.ParameterMetadata
WarningAction System.Management.Automation.ParameterMetadata
InformationAction System.Management.Automation.ParameterMetadata
ProgressAction System.Management.Automation.ParameterMetadata
ErrorVariable System.Management.Automation.ParameterMetadata
WarningVariable System.Management.Automation.ParameterMetadata
InformationVariable System.Management.Automation.ParameterMetadata
OutVariable System.Management.Automation.ParameterMetadata
OutBuffer System.Management.Automation.ParameterMetadata
PipelineVariable System.Management.Automation.ParameterMetadata
WhatIf System.Management.Automation.ParameterMetadata
Confirm System.Management.Automation.ParameterMetadata
檢查管道輸入屬性
# 顯示 cmdlet 所有參數,並檢查其管道輸入屬性
PS /Users/kanglin/code/30days> (Get-Command Stop-Process).Parameters.GetEnumerator() | ForEach-Object {
>> [PSCustomObject]@{
>> Name = $_.Key
>> AcceptsPipeline = $_.Value.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] } | Select-Object -ExpandProperty ValueFromPipeline
>> AcceptsProperty = $_.Value.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] } | Select-Object -ExpandProperty ValueFromPipelineByPropertyName
>> }
>> }
Name AcceptsPipeline AcceptsProperty
---- --------------- ---------------
Name False True
Id False True
InputObject True False
PassThru False False
Force False False
Verbose False False
Debug False False
ErrorAction False False
WarningAction False False
InformationAction False False
ProgressAction False False
ErrorVariable False False
WarningVariable False False
InformationVariable False False
OutVariable False False
OutBuffer False False
PipelineVariable False False
WhatIf False False
Confirm False False
這可以幫助你清楚地看到哪些參數支援管道輸入,即使 Get-Help 沒有明確說明。
透過這個案例,理解如何將 Import-CSV
的 output 透過 pipeline 使用 PropertyName 傳遞給 New-Alias
PS /Users/kanglin/code/30days> cat ./aliases.txt
Name,Value
d,Get-ChildItem
sel,Select-Object
go,Invoke-Command
Import-CSV
將文件內容轉化成 Object# 匯入
PS /Users/kanglin/code/30days> Import-Csv ./aliases.txt
Name Value
---- -----
d Get-ChildItem
sel Select-Object
go Invoke-Command
# 檢查屬性
PS /Users/kanglin/code/30days> Import-Csv ./aliases.txt | gm
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Name NoteProperty string Name=d
Value NoteProperty string Value=Get-ChildItem
New-Alias
接收 Import-CSV
傳遞的物件並建立新的 aliasNew-Alias
的 Syntax-Name & -Value 對應著 Import-CSV 的 output object 屬性裡的 Name & Valuee
PS /Users/kanglin/code/30days> get-help New-Alias
NAME
New-Alias
SYNOPSIS
Creates a new alias.
SYNTAX
New-Alias [-Name] <System.String> [-Value] <System.String> [-Description <System.String>] [-Force] [-Option {None | ReadOnly | Constant | Private | AllScope | Unspecified}] [-PassThru] [-Scope <System.St
ring>] [-Confirm] [-WhatIf] [<CommonParameters>]
ByPropertyName
方式所輸入的內容PS /Users/kanglin/code/30days> get-help New-Alias -Parameter Name
-Name <System.String>
Specifies the new alias. You can use any alphanumeric characters in an alias, but the first character cannot be a number.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
PS /Users/kanglin/code/30days> get-help New-Alias -Parameter Value
-Value <System.String>
Specifies the name of the cmdlet or command element that is being aliased.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
Import-Csv ./aliases.txt | New-Alias
結果會產生三個全新的別名,名為 d、sel 和 go,分別對應 Get-ChildItem、Select-Object、Invoke-Command 的命令。
今天探討了 PowerShell 的管道參數綁定機制,展示了如何透過 ByValue 和 ByPropertyName 自動匹配前後命令的輸入和輸出。這種自動化的資料傳遞方式大大簡化了命令的使用,省去了手動處理變數和參數的麻煩。特別是當命令間具有相似結構或屬性時,這些匹配機制顯得更加方便和直觀。
Day 11 - 深度探索管線 Part 2