Home Dashboard Directory Help
Search

Where-Object & Select-Object: InputObject Parameter does not work as expected by Trevor Sullivan


Status: 

Active


19
4
Sign in
to vote
Type: Bug
ID: 716546
Opened: 1/4/2012 1:23:39 PM
Access Restriction: Public
1
Workaround(s)
view
5
User(s) can reproduce this bug

Description

The Where-Object cmdlet's parameter named -InputObject does not work as expected. According to the help documentation for Where-Object, you can either pipe a collection of objects into Where-Object, or use -InputObject instead. In some cases, I prefer to use -InputObject, as I do not always like using the pipeline during script development.

Consider the following command, which does not produce expected output:

Where-Object -InputObject:1,2,3 -FilterScript:{ $_ -eq 1 };

The above command outputs:
1
2
3

Now, consider the following command, which produces the desired output:

1,2,3 | Where-Object -FilterScript:{ $_ -eq 1 };

The output produced is:
1

The two commands described above should have similar behavior. There is no point in filtering a single .NET object using Where-Object's -InputObject parameter.

---------------------------------------------------------------------------------------------------------
The same applies to the -InputObject parameter on the Select-Object cmdlet. Consider the output from the following two commands:

# EXAMPLE 1
1..5 | Select-Object -First 2;

# Output:
# 1
# 2

# EXAMPLE 2
Select-Object -First 2 -InputObject (1..5);

# Output:
# 1
# 2
# 3
# 4
# 5

Why on earth would you want this to behave like this? In the latter Select-Object example, it doesn't even make sense to treat it as a singleton, because you are selecting the first *two* objects. If only one object is put in, then why would you even use the -First X, or -Last Y, parameters? Or, why would you use the -Unique parameter, when if you only have one object anyway, it is by definition unique?
Details
Sign in to post a comment.
Posted by Trevor Sullivan on 6/5/2012 at 10:29 AM
Kirk,

As I mentioned below, the -InputObject parameter works correctly on ForEach-Object. I was simply using that evidence to reinforce my argument that Select-Object and Where-Object should act similarly.

To your points:

1) ForEach-Object is not consistent with Select-Object and Where-Object
2) As I have already mentioned, there are other breaking changes in PowerShell v3, so why would this bug not be fixed as well? Many of the other breaking changes are not even bug fixes, but simply functionality changes. That argument doesn't hold a lot of water. Additionally, why should something that's broken not be fixed, especially when the documentation explicitly states that it can be used either way?

With this in mind, please retract your downvote at the very least, and I hope you see the light enough to upvote it.

Trevor
Posted by Kirk Munro on 6/5/2012 at 10:16 AM
I'm with them leaving this as is. InputObject is a singleton in ForEach-Object. You can see that in this example:

# EXAMPLE 1
1..5 | % { $_.GetType().FullName}

# Output:
# System.Int32
# System.Int32
# System.Int32
# System.Int32
# System.Int32

# EXAMPLE 2
% -In (1..5) {$_.GetType().FullName}

# Output:
# System.Object[]

The reason you see the array output in both cases is because of how PowerShell handles the display of arrays, showing their contents.

With that in mind, the PowerShell team is right leaving this the way it is. This shouldn't change because: (a) it's consistent (as shown above) and (b) changing it would risk breaking scripts unnecessarily.

There are other ways this could be resolved without breaking anything. For example, you could request an optional switch parameter to expand the array, and in v3 if you want that to always be used, well you can set the default value for that to true in your profile. That's just one example of how this could be implemented without breaking anything. You'll probably get a lot farther with your request that way, but I wouldn't expect anything to happen in v3 at this point given that they've already made the Release Preview public.
Posted by Trevor Sullivan on 6/4/2012 at 12:28 PM
Also consider how the -InputObject parameter on ForEach-Object works -- the output matches on both examples, as expected! Imagine if you treated -InputObject as a singleton object on the ForEach-Object cmdlet ... it wouldn't make sense, would it?

Neither does it make sense for Select-Object and Where-Object.

# EXAMPLE 1
1..5 | % { $_ };

# Output:
# 1
# 2
# 3
# 4
# 5

# EXAMPLE 2
% -In (1..5) { $_ };

# Output:
# 1
# 2
# 3
# 4
# 5
Posted by Trevor Sullivan on 6/4/2012 at 11:57 AM
Bug has been re-opened to "active" state.
Posted by Trevor Sullivan on 6/4/2012 at 10:30 AM
As Joel notes in his blog post: Why on earth would you need -InputObject to take a singleton object (for Where-Object & Select-Object)? If I feed it an array of objects, just as with pipeline input, then why would it treat the array as a single object? I have no need to use Where-Object to filter a *single* object; that pretty much defeats its purpose.

Regardless of the above, the documentation for the -InputObject parameter on the Where-Object & Select-Object cmdlets (and probably others) dictates this: "Specifies the objects to be filtered. You can also pipe the objects to <CmdletName>." To me, that sounds like an interchangeable, either/or scenario ... either 1) pipe the objects to the cmdlet, or 2) use the -InputObject parameter. So, why would the documentation state this, but then the cmdlet acts differently?

I happen to *want* to use the -InputObject parameter due to performance problems using the PowerShell pipeline. When developing scripts, I avoid the use of the pipeline, and instead use cmdlets more sparingly. When I do use cmdlets, I treat them more like .NET method calls than cmdlets with pipeline support. I do not want to be *forced* into using the PowerShell pipeline, however I also do not want to re-invent the wheel by writing my own version of Select-Object, Get-Member, and so on.

Please make this right. I'm surprised that it needs to be argued.
Posted by ZappedC64 on 6/4/2012 at 10:01 AM
Please fix this, this bug has constantly caused me to find other ways to work with objects.
Posted by Trevor Sullivan on 6/4/2012 at 7:55 AM
Corresponding link to last comment:

http://huddledmasses.org/whats-the-desired-behavior-of-inputobject/
Posted by Trevor Sullivan on 6/4/2012 at 7:55 AM
The behavior is incredibly irritating. Joel Bennett has a post on this very same topic all the way back from 2007. There are quite a few breaking changes in PowerShell v3 from v2, so why would this not be considerable?
Posted by Microsoft on 1/6/2012 at 4:36 PM
InputObject takes input as a singleton which is why you're seeing it treat 1,2,3 as a single object. This behavior has existed since PowerShell v1 and cannot be changed for v3.
Sign in to post a workaround.
Posted by Trevor Sullivan on 1/4/2012 at 1:24 PM
The only known workaround for this bug is to use pipeline input for Where-Object.