Search code examples
powershellpipelinepowershell-4.0

Which commands operate on a single item and which take an array of objects?


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.


Solution

  • 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.