How do you send the output from one CmdLet to the next one in a pipeline as a complete array-object instead of the individual items in the array one at a time?
The problem - Generic description
As can be seen in help for about_pipelines (help pipeline
) powershell sends objects one at the time down the pipeline¹. So Get-Process -Name notepad | Stop-Process
sends one process at the time down the pipe.
Lets say we have a 3rd party CmdLet (Do-SomeStuff) that can't be modified or changed in any way. Do-SomeStuff perform different if it is passed an array of strings or if it is passed a single string object.
Do-SomeStuff is just an example, it could be substituted for ForEach-Object
, Select-Object
, Write-Host
(or any other CmdLet accepting pipeline input)
Do-SomeStuff will in this example process the individual items in the array one at the time.
$theArray = @("A", "B", "C")
$theArray | Do-SomeStuff
If we want to send the complete array as one object to Do-SomeStuff one might try something like this
@($theArray) | Do-SomeStuff
But it does not produce the expected result since PowerShell "ignores" the new single-item-array.
So, how do you "force" $theArray
to be passed down the pipe as a single array-object instead of the content items one at the time?
The problem - practical example
As shown below the output of Write-Host
is different if passed an array or if it passed the individual items in the array one at the time.
PS C:\> $theArray = @("A", "B", "C")
PS C:\> Write-Host $theArray
A B C
PS C:\> $theArray | foreach{Write-Host $_}
A
B
C
PS C:\> @($theArray) | foreach{Write-Host $_}
A
B
C
How do you do to get $theArray | foreach{Write-Host $_}
to produce the same output as Write-Host $theArray
?
FOOTNOTES
- Pipeline processing in Powershell
A normal array of strings
PS C:\> @("A", "B", "C").GetType().FullName
System.Object[]
A normal array of strings piped to Foreach-Object
PS C:\> @("A", "B", "C") | foreach{$_.GetType().FullName}
System.String
System.String
System.String
Each string in the array is processed one at the time by the ForEach-Object CmdLet.
An array of arrays, where the "inner" arrays are arrays of strings.
PS C:\> @(@("A", "B", "C"), @("D", "E", "F"), @("G", "H", "I")) | foreach{$_.GetType().FullName}
System.Object[]
System.Object[]
System.Object[]
Each array in the array is processed one at the time by the ForEach-Object CmdLet, and the content of each sub-array from the input is handled as one object even though it is an array.
@(@(@()))
and get more than a single array (roughly). – Skylark@()
not work for that? – Skylark"A", "B", "C" | Format-Custom -Expand CoreOnly
proves you are pushing whole array to theFormat-Custom
cmdlt, so what do you want? – Festus