2

Issue

Calling the Where-Object cmdlet returns different outputs if the same PSObject is passed using the pipe or the -InputObject parameter:

  1. When using the pipe, the condition is applied.
  2. When using the -InputObject parameter, the condition is ignored.

Question

Why does the condition not apply when the -InputObject parameter is used?

MWE

Consider the following directory:

PS C:\> Get-ChildItem -Path "C:\tmp\mwe"


    Directory: C:\tmp\mwe


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        07/07/2021     15:51              0 a.txt
-a----        07/07/2021     15:54              0 b.csv
-a----        07/07/2021     15:53              0 c.log

Using pipe

When piping Get-ChildItem to Where-Object, the condition is properly applied and the text file is excluded from the output.

PS C:\> Get-ChildItem -Path "C:\tmp\mwe" | Where-Object -Property "Name" -NotMatch -Value "\.txt"


    Directory: C:\tmp\mwe


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        07/07/2021     15:54              0 b.csv
-a----        07/07/2021     15:53              0 c.log

Using -InputObject parameter

When using the -InputObject parameter, the condition is not applied and the text file is not excluded from the output.

PS C:\> Where-Object -InputObject (Get-ChildItem -Path "C:\tmp\mwe") -Property "Name" -NotMatch -Value "\.txt"


    Directory: C:\tmp\mwe


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        07/07/2021     15:51              0 a.txt
-a----        07/07/2021     15:54              0 b.csv
-a----        07/07/2021     15:53              0 c.log
Akaizoku
  • 456
  • 5
  • 19
  • 1
    In the last example you're asking `Where-Object` to evaluate the whole array as a single thing at once, as opposed to evaluating the items 1 by 1. Since `(Get-ChildItem).Name` evaluates to a collection where at least one item satisfies the condition, the entire array filters through. – Mathias R. Jessen Jul 07 '21 at 16:09
  • 1
    I think this inconsistency is described in this PowerShell issue: [`#4242` Consistently document a scalar -InputObject parameter as an implementation detail or make item-by-item processing cmdlets explicitly iterate over collections](https://github.com/PowerShell/PowerShell/issues/4242) from @mklement0 – iRon Jul 07 '21 at 16:28

1 Answers1

1

After careful reading of the pipeline documentation, this distinct behaviour is indeed intended.

Piping objects to a command is much like using a parameter of the command to submit the objects.

[...]

However, there's an important difference. When you pipe multiple objects to a command, PowerShell sends the objects to the command one at a time. When you use a command parameter, the objects are sent as a single array object. This minor difference has significant consequences.

Thank you Mathias R. Jessen and iRon for pointing that out in the comments.

Akaizoku
  • 456
  • 5
  • 19