How do I output text without a newline in PowerShell?
PowershellPowershell Problem Overview
I want my PowerShell script to print something like this:
Enabling feature XYZ......Done
The script looks something like this:
Write-Output "Enabling feature XYZ......."
Enable-SPFeature...
Write-Output "Done"
But Write-Output
always prints a new-line at the end so my output isn't on one line. Is there a way to do this?
Powershell Solutions
Solution 1 - Powershell
Write-Host -NoNewline "Enabling feature XYZ......."
Solution 2 - Powershell
Unfortunately, as noted in several answers and comments, Write-Host
can be dangerous and cannot be piped to other processes and Write-Output
does not have the -NoNewline
flag.
But those methods are the "*nix" ways to display progression, the "PowerShell" way to do that seems to be Write-Progress
: it displays a bar at the top of the PowerShell window with progress information, available from PowerShell 3.0 onward, [see manual][1] for details.
# Total time to sleep
$start_sleep = 120
# Time to sleep between each notification
$sleep_iteration = 30
Write-Output ( "Sleeping {0} seconds ... " -f ($start_sleep) )
for ($i=1 ; $i -le ([int]$start_sleep/$sleep_iteration) ; $i++) {
Start-Sleep -Seconds $sleep_iteration
Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) ( " {0}s ..." -f ($i*$sleep_iteration) )
}
Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) -Completed "Done waiting for X to finish"
And to take the OP's example:
# For the file log
Write-Output "Enabling feature XYZ"
# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... " )
Enable-SPFeature...
# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... Done" )
# For the log file
Write-Output "Feature XYZ enabled"
[1]: https://technet.microsoft.com/en-us/library/hh849902.aspx "Write-Progress on MS TechNet"
Solution 3 - Powershell
While it may not work in your case (since you're providing informative output to the user), create a string that you can use to append output. When it's time to output it, just output the string.
Ignoring of course that this example is silly in your case but useful in concept:
$output = "Enabling feature XYZ......."
Enable-SPFeature...
$output += "Done"
Write-Output $output
Displays:
Enabling feature XYZ.......Done
Solution 4 - Powershell
To write to a file you can use a byte array. The following example creates an empty ZIP file, which you can add files to:
[Byte[]] $zipHeader = 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
[System.IO.File]::WriteAllBytes("C:\My.zip", $zipHeader)
Or use:
[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:\My.zip", $text)
Solution 5 - Powershell
Yes, as other answers have states, it cannot be done with Write-Output. Where PowerShell fails, turn to .NET, there are even a couple of .NET answers here but they are more complex than they need to be.
Just use:
[Console]::Write("Enabling feature XYZ.......")
Enable-SPFeature...
Write-Output "Done"
It is not purest PowerShell, but it works.
Solution 6 - Powershell
The problem that I hit was that Write-Output actually linebreaks the output when using using PowerShell v2, at least to stdout. I was trying to write an XML text to stdout without success, because it would be hard wrapped at character 80.
The workaround was to use
[Console]::Out.Write($myVeryLongXMLTextBlobLine)
This was not an issue in PowerShell v3. Write-Output seems to be working properly there.
Depending on how the PowerShell script is invoked, you may need to use
[Console]::BufferWidth =< length of string, e.g. 10000)
before you write to stdout.
Solution 7 - Powershell
There seems to be no way to do this in PowerShell. All of the previous answers are not correct, because they do not behave the way Write-Output
behaves but more like Write-Host
which doesn't have this problem anyway.
The closes solution seems to use Write-Host
with the -NoNewLine
parameter. You can not pipe this which is a problem generally, but there is a way to override this function as described in https://stackoverflow.com/questions/9294221/write-host-export-to-a-file/28370042#28370042, so you can easily make it accept the parameter for an output file. This is still far from a good solution. With Start-Transcript
this is more usable, but that cmdlet has problems with native applications.
Write-Output
simply can't do what you need in a general context.
Solution 8 - Powershell
I cheated, but I believe this is the only answer that addresses every requirement. Namely, this avoids the trailing CRLF, provides a place for the other operation to complete in the meantime, and properly redirects to stdout as necessary.
$c_sharp_source = @"
using System;
namespace StackOverflow
{
public class ConsoleOut
{
public static void Main(string[] args)
{
Console.Write(args[0]);
}
}
}
"@
$compiler_parameters = New-Object System.CodeDom.Compiler.CompilerParameters
$compiler_parameters.GenerateExecutable = $true
$compiler_parameters.OutputAssembly = "consoleout.exe"
Add-Type -TypeDefinition $c_sharp_source -Language CSharp -CompilerParameters $compiler_parameters
.\consoleout.exe "Enabling feature XYZ......."
Write-Output 'Done.'
Solution 9 - Powershell
A simplification to FrinkTheBrave's response:
[System.IO.File]::WriteAllText("c:\temp\myFile.txt", $myContent)
Solution 10 - Powershell
The answer by shufler is correct. Stated another way: Instead of passing the values to Write-Output using the ARRAY FORM,
Write-Output "Parameters are:" $Year $Month $Day
or the equivalent by multiple calls to Write-Output,
Write-Output "Parameters are:"
Write-Output $Year
Write-Output $Month
Write-Output $Day
Write-Output "Done."
concatenate your components into a STRING VARIABLE first:
$msg="Parameters are: $Year $Month $Day"
Write-Output $msg
This will prevent the intermediate CRLFs caused by calling Write-Output multiple times (or ARRAY FORM), but of course will not suppress the final CRLF of the Write-Output commandlet. For that, you will have to write your own commandlet, use one of the other convoluted workarounds listed here, or wait until Microsoft decides to support the -NoNewline
option for Write-Output.
Your desire to provide a textual progress meter to the console (i.e. "....") as opposed to writing to a log file, should also be satisfied by using Write-Host. You can accomplish both by collecting the msg text into a variable for writing to the log AND using Write-Host to provide progress to the console. This functionality can be combined into your own commandlet for greatest code reuse.
Solution 11 - Powershell
Write-Host
is terrible, a destroyer of worlds, yet you can use it just to display progress to a user whilst using Write-Output
to log (not that the OP asked for logging).
Write-Output "Enabling feature XYZ" | Out-File "log.txt" # Pipe to log file
Write-Host -NoNewLine "Enabling feature XYZ......."
$result = Enable-SPFeature
$result | Out-File "log.txt"
# You could try{}catch{} an exception on Enable-SPFeature depending on what it's doing
if ($result -ne $null) {
Write-Host "complete"
} else {
Write-Host "failed"
}
Solution 12 - Powershell
You simply cannot get PowerShell to omit those pesky newlines... There is no script or cmdlet that does. Of course, Write-Host is absolute nonsense, because you can't redirect/pipe from it!
Nevertheless, you can write your own EXE file to do it which is what I explained how to do in Stack Overflow question https://stackoverflow.com/questions/2038181/how-to-output-something-in-powershell/11901810#11901810.
Solution 13 - Powershell
The following will place the cursor back at beginning of the previous row. It's up to you to place it in the right horizontal position (using $pos.X to move it sideways):
$pos = $host.ui.RawUI.get_cursorPosition()
$pos.Y -= 1
$host.UI.RawUI.set_cursorPosition($Pos)
Your current output is 27 spaces over, so $pos.X = 27 might work.
Solution 14 - Powershell
It may not be terribly elegant, but it does exactly what OP requested. Note that the ISE messes with StdOut, so there will be no output. In order to see this script work it can't be run within the ISE.
$stdout=[System.Console]::OpenStandardOutput()
$strOutput="Enabling feature XYZ... "
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
Enable-SPFeature...
$strOutput="Done"
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
$stdout.Close()
Solution 15 - Powershell
$host.UI.Write('Enabling feature XYZ.......')
Enable-SPFeature...
$host.UI.WriteLine('Done')
Solution 16 - Powershell
Simplest way with in-line concatenation - and while moving across to 'Write-Output' instead; e.g. 2 tab characters (string) & then a literal/verbatim (string):
Write-Output ("`t`t" + '${devArg}')
Solution 17 - Powershell
I'm not an expert by any means, but why not this:
Write-Output "hello" | ForEach-Object { $PSItem.Trim() } | Do-Whatever
This maintains the pipeline semantics but just trims the new line characters before passing it on down the pipeline to whatever you need to do next. If that is writing to a file, so be it. If that is writing to the host, you can do that, but if you do write it to the host, remember to use | Write-Host -NoNewline
UPDATE: As per my comment below: "I see why my answer won't work.. Powershell inevitable appends a new line char as part of it's piping semantics when piping to external programs. See this: github.com/PowerShell/PowerShell/issues/5974 Therefore when I pass the trimmed text down the pipeline, the new line char will re-appear in the input."
Solution 18 - Powershell
desired o/p: Enabling feature XYZ......Done
you can use below command
$a = "Enabling feature XYZ"
Write-output "$a......Done"
you have to add variable and statement inside quotes. hope this is helpful :)
Thanks Techiegal
Solution 19 - Powershell
You can absolutely do this. Write-Output has a flag called "NoEnumerate" that is essentially the same thing.