4

I'm trying to understand Powershell, but find somethings not so intuitive. What I understand of it is that in the pipeline objects are passed, instead of traditionally text. And $_ refers to the current object in the pipeline. Then, why is the following not working:

get-date|Write-Host "$_"

The errormessage is:

Write-Host : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not matc
h any of the parameters that take pipeline input.
At line:1 char:10
+ get-date|Write-Host $_
+          ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (10-9-2014 15:17:00:PSObject) [Write-Host], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.WriteHostCommand
0

3 Answers 3

11

$_ is the current single item in the pipeline. To write each item in the pipeline you would write

get-data | foreach { Write-Host $_ }

Or in the short form

get-data |% { Write-Host $_ }

Conceptually, Foreach is a cmdlet that receives a function parameter, a pipeline input and applies the function on each item of the pipeline. You can't just write code with $_ - you need to have a function explicitly states that it agrees to receive pipeline input

Sign up to request clarification or add additional context in comments.

3 Comments

OK, I kind of get this, but not entirely. According to "get-help Write-Host -parameter *", positional parameter -Object accepts pipeline input and indeed "get-date|Write-Host" works. So then, what's the difference with using $_ as a substitute for the pipeline input and the command using the pipeline input directly. Is it just because $_ is an array (hence the foreach is needed) and in that case would you be able to get the first item like $_[0]?
While Write-Host is willing to get it's input from the pipeline (i.e. the Object parameter is automatically bound to the pipeline if not specified), what you did with Write-Host $_ was to specify the object, so it was bound to $_ and not the pipeline. But $_ is not really the pipeline data - it's a variable which is only defined by the foreach function for the function you give it
1

And $_ refers to the current object in the pipeline

Indeed, the automatic $_ variable refers to the current pipeline input object, but only in script blocks ({ ... }), notably those passed to the ForEach-Object and Where-Object cmdlets.

Outside of script blocks it has no meaningful value.

Therefore, the immediate fix to your command is the following:

# Note: 
# * Get-Date *alone* is preferable; its output *implicitly* prints.
# * If you want to use Write-Host, this is better: Get-Date | Write-Host
Get-Date | ForEach-Object { Write-Host $_ }

However, note that:

  • Write-Host is is often the wrong tool to use, unless the intent is to write to the display only, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file.

  • To output a value (which prints to the display by default), simply don't capture it, if it is a command's output (e.g., Get-Date) or, if it is stored in a variable, use the latter by itself; e.g, $value, instead of Write-Host $value (or use Write-Output $value); see this answer.
    To explicitly print only to the display (instead of outputting data), but with rich formatting, use Out-Host.

Therefore, if merely outputting each pipeline input object is the goal, Get-Date | ForEach-Object { $_ } would do, where the ForEach-Object call is redundant if each input object is to simply be passed through (without transformation); that is, in the latter case just Get-Date would do.


As for what you tried:

get-date|Write-Host "$_"

As noted, the use of $_ in this context is pointless, but the reason for the error message you saw is unrelated to that problem:

Instead, the reason for the error is that you're mistakenly trying to provide input to Write-Host both via the pipeline (Get-Date | Write-Host ...) and by way of an argument (... | Write-Host "...").

  • Given that the argument ("$_") (positionally) binds to the -Object parameter, the pipeline input then has no parameter left to bind to, which causes the error at hand.

Comments

0

The closest I can get is this. For some reason, "write-host -object { $_ }" doesn't take, I think because the parameter type is object. $_ has to be in a script block with a parameter that takes pipeline input. Commandlets or functions don't take their arguments in parentheses.

get-date | write-output -inputobject { $_ } # need parameter name

Wednesday, November 13, 2024 8:35:46AM

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.