-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Being able to pass script blocks ad hoc in order to calculate per-input-object parameter values is a great general-purpose feature.
However, it is currently limited to parameters that are explicitly defined as pipeline-binding.
A widely used application of this technique is with Rename-Item's -NewName parameter, where a script block is passed to calculate the new name; e.g.:
# Rename all *.rtf files to *.txt files
Get-Item *.rtf | Rename-Item -NewName { $_.BaseName + '.txt' } -WhatIfHowever, the above only works because -NewName too is defined as pipeline-binding (ValueFromPipelineByPropertyName, in this case).
The ability to pass a script block to any parameter (other than those typed [object] or [scriptblock]) of a command that accepts pipeline input in principle - whether or not that parameter is itself pipeline-binding - would make this technique useful in a much wider array of situations.
Is there a conceptual barrier to removing this restriction (overall, the cmdlet/advanced function would still have to have at least one pipeline-binding parameter)?
Technically, this would be a breaking change, albeit hopefully one that falls into Bucket 3: Unlikely Grey Area:
What happens currently if you try to pass a script block to a differently typed non-pipeline-binding parameters is that an attempt is made to convert the script block to the parameter's type (unless the parameter is [object] or [scriptblock], which would continue to be exempt).
This fails with most types, but in the case of a [string] parameter you currently do get the script block's contents as a string value.
Arguably, though, users who expect script blocks type their parameters a such.
Here's an example with an advanced function:
function Rename-Foo {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[System.IO.FileSystemInfo] $InputObject
,
# WISHFUL THINKING: The `ValueFromPipelineByPropertyName` shouldn't be necessary.
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string] $NewName
)
process {
"Will rename $($InputObject.Name) to $NewName."
}
}
PS> Get-Item foo.txt, bar.txt | Rename-Foo -NewName { $_.Name + '!!' }
Will rename foo.txt to foo.txt!!
Will rename bar.txt to bar.txt!!Environment data
Written as of:
PowerShell Core v6.0.2