I've been trying to learn PowerShell and am currently looking at piping the output of one command into the input of another. I've found that some commands can operate on an array of items that are piped in while other commands can only operate on a single item in an array.
For example, Where-Object
can operate on an array of items, returning a subset of them, whereas New-Item
can only operate on a single item.
I have to handle the two types of commands differently, with commands that can only operate on a single item having to be enclosed in a ForEach-Object
block.
For intance, Where-Object
doesn't need a ForEach-Object
:
Get-Service | where Status -eq "Stopped"
But New-Item
does:
@("Red", "Blue", "Green") | foreach {new-item -Name $_ -ItemType directory}
How can I determine whether a particular command can act on an array of items, or whether it can only act on a single item?
As far as I can see the help doesn't really give a clue. For example the help for Where-Object
states the input type is System.Management.Automation.PSObject
, which doesn't imply to me it can be an array of objects.
EDIT: aljodAv has pointed out in his answer that ForEach-Object
is not actually needed in the second example. It can be written as:
@("Red", "Blue", "Green") | new-item -Name {$_} -ItemType directory
The question still stands, however, as $_ represents the current item from the collection object passed through the pipeline.
I don't think that this is a matter of which can accept an array and which can't, this is more an issue of what cmdlets accept piped input, and which don't, and for the ones that do accept it, how do they use the objects piped into them. For the most part you will want to look at the help for whatever cmdlet you are interested in to see if it accepts piped input.
Now, Where-Object
is designed to work on an array of objects piped into it, so it doesn't specifically state that it does, and assumes that the user is going to be able to figure that out. New-Item
actually does take an array of objects to be piped into it, but the parameter that accepts that is the -Value
parameter, so that may be a bit less useful for most people. Your example above shows that you want to specify the -Name
parameter, which does not accept piped values.
So the answer to your question is that anything that accepts piped input will allow you to pipe an array of the correct object type into it and it will process each item in turn, the challenge can be in finding if or how an object will accept piped information.
For your specific example, I personally think that New-Item
should have accepted piped strings to accommodate the creation of either directories or empty files, or allow piped objects/hashtables to allow for the creation of more complex things.