Pipeline-aware functions compose with built-in cmdlets and stream large inputs efficiently.
Adding [CmdletBinding()] above param() turns a function into an advanced function. It gains the common parameters (-Verbose, -ErrorAction, -WhatIf when declared...) and the $PSCmdlet object.
To accept pipeline input, mark a parameter with ValueFromPipeline (the whole object binds) or ValueFromPipelineByPropertyName (a property with the same name, or an [Alias()], binds). The function body is then split into blocks:
begin { }runs once before the first item: initialise counters, open connections,process { }runs once per pipeline item, with the parameter bound to that item,end { }runs once at the end: totals, cleanup.
Without a process block the whole body acts like end and only sees the last item. Declare array parameters ([string[]]) and loop inside process, so the function works both when piped and when called with several values directly.
For commands that change things, add [CmdletBinding(SupportsShouldProcess)] and guard changes with if ($PSCmdlet.ShouldProcess($target, 'Delete')) { ... }. Your function then supports -WhatIf and -Confirm automatically, just like Remove-Item. Emit objects with [pscustomobject] rather than formatted text so callers can keep piping.
Example
function Get-FileSizeKB {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[Alias('FullName')]
[string[]]$Path
)
begin { $total = 0 }
process { # once per pipeline item
foreach ($p in $Path) {
$kb = [math]::Round((Get-Item $p).Length / 1KB, 1)
$total += $kb
[pscustomobject]@{ File = Split-Path $p -Leaf; KB = $kb }
}
}
end { Write-Verbose "total: $total KB" }
}
Get-ChildItem $PSHOME -Filter *.json | Get-FileSizeKB -Verbose # FullName binds to Path
Get-FileSizeKB -Path (Join-Path $PSHOME 'pwsh.dll') # direct callRemember
- [CmdletBinding()] adds common parameters like -Verbose
- ValueFromPipeline / ByPropertyName bind piped objects
- begin once, process per item, end once; SupportsShouldProcess adds -WhatIf
Watch out for
- Omitting the process block, so a piped function only handles the last item.