-5

I am a newcomer to PS scripting. I have found that, generally speaking, PS adds a lot of newlines to output of its commands. I am giving below a couple of examples of what I found somewhat generalized about the (default?) output in PS commands. I am used to Unix-like output, where the generalized output has few to none of these lines (of course, nothing prevents a programmer from adding them).

Is there a configurable way to reduce the amount of those newlines, and perhaps the verbosity?

I have compiled below a list of SO questions (and extra) dealing with specific cases, but none aims at a general setting. I could apply some of the answers on a command-by-command basis, but I am asking if there is some form of overall setting/configuring PS.

EDIT: Later on I found this similar question (with a slight variation) in SU.


Examples

This is what I see with a couple of commands

> dir
                                                                                                    ******  EXTRA LINE
                                                                                                    ******  EXTRA LINE
    Directorio: C:\Users\USER1\OneDrive - YPF\Documents\soft-hard-ware\windows\powershell           ******  VERBOSITY LINE
                                                                                                    ******  EXTRA LINE
                                                                                                    ******  EXTRA LINE
Mode                LastWriteTime         Length Name                                               ******  VERBOSITY LINE
----                -------------         ------ ----                                               ******  VERBOSITY LINE
-a----         9/7/2020     17:11           1021 exec_powershell_info.txt
-a----         9/4/2016     08:25            281 first_bytes.ps1
-a----        10/7/2020     07:53           1536 get_current_script_name.ps1
-a----         9/7/2020     11:58             29 hello_world.ps1
-a----         9/4/2016     09:02            344 last_bytes.ps1
-a----        14/4/2016     13:08            975 split.ps1
-a----        10/7/2020     07:54           3108 update-help.txt
                                                                                                    ******  EXTRA LINE
                                                                                                    ******  EXTRA LINE
> Get-Culture
                                                                                                    ******  EXTRA LINE
LCID             Name             DisplayName                                                       ******  VERBOSITY LINE
----             ----             -----------                                                       ******  VERBOSITY LINE
11274            es-AR            Español (Argentina)                                                                  
                                                                                                    ******  EXTRA LINE
                                                                                                    ******  EXTRA LINE

Scrolling to the right, one can see my comments. I have tagged "EXTRA LINE" the lines I mean to remove. I have tagged "VERBOSITY LINE" the lines I mean to remove, but which I sort of "tolerate" more.

As a point in comparison, this is what I see in Linux, which I find "less verbose".

$ ll
total 12K
drwxrwxr-x  2 santiago santiago 4,0K ago 10  2017 ./
drwxrwxr-x 17 santiago santiago 4,0K may 19 10:28 ../
-rwxrwxr-x  1 santiago santiago  557 ago 10  2017 date2str.rb*

List of other sources that do not address the issue

  1. Remove blank lines in powershell output
  2. Remove blank lines Powershell output
  3. Removing Blank Lines From Powershell Output
  4. How to remove extra lines from Get-WMIObject output powershell
  5. Remove blank lines from output?
  6. Remove Blank Space From Output in PowerShell
  7. Remove Empty Lines From Powershell Output
  8. Removing extra blank space from PowerShell output
  9. Remove blank lines from the output
  10. https://social.technet.microsoft.com/Forums/en-US/229727f6-fdb6-4d95-b585-bd9af3ee6670/removing-blank-spaces-and-blank-lines-from-output?forum=ITCG
  • 4
    Are you essentially asking all of the readers to visit ten links read through all of the information on them, then suggest something which has not been mentioned in all of those? Asking for general solutions to encompass every possible output is just not a realistic question. If you have a specific issue with a particular output, we can try to provide you with a solution. Other than essentially reprogramming PowerShell, or programming a helper application or script which takes everything output, parses it, modifies it and then outputs it as you want, your question is probably unanswerable. – Compo Jul 10 '20 at 11:52
  • 1
    I've never noticed an excess of blank lines in PowerShell. Can you give an example of where you see this? As for the verbose output, that depends on the command (and switches) you run, but PowerShell provides a lot of scope for customising or suppressing it. Again, can you give an example where you have verbose output and what you'd actually like to see instead? – boxdog Jul 10 '20 at 11:52
  • 3
    please recall that what you see on screen IS NOT THE OBJECT. it's a text representation of the object and may have items added AND/OR removed to make the display human readable. so ... **_what EXACT problem are you dealing with? is it the on-screen display or the actual data?_** – Lee_Dailey Jul 10 '20 at 12:55
  • For display purposes only, send everything to `Out-String` and `Trim()` the excess. `(Command | Out-String).Trim()`. However, I don't recommend changing the output type of your objects. I'd just live with it as it is. – AdminOfThings Jul 10 '20 at 13:01
  • `select-string pattern | % line` – js2010 Jul 10 '20 at 13:02
  • The comment from @Lee_Daily is correct. When PowerShell outputs to the console window, it is outputting _conveniently formatted textual representations of objects_. The short answer to your question is thus: Don't worry about the extra spaces. A simple example: `Get-ChildItem` (for a file system directory) produces formatted representations of file system items. – Bill_Stewart Jul 10 '20 at 14:51
  • 1
    @Compo - "Are you essentially asking all of the readers...?" **No**, why would you think so? I just posted the list to make it explicit that I have read them and, unless I missed something, there is no solution to my OP there. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 14:54
  • Unless you listed in your question proper each of the pieces of information you gleaned from those links, and provided examples of the solutions within them in action, with an actual code example and an explanation of how each failed to achieve your goal, then of course you expected that! Without doing so, I could for instance just take any one of those SO pages, and close your question as a duplicate of one or more of them, and it's clear that you don't want that. So, as already mentioned, without an actual command, real output, and how you want it to look instead, your question is too broad. – Compo Jul 10 '20 at 14:59
  • @Compo - I am intrigued by your point of view about the question. There might be a setting in PowerShell to control such output, which I do not know about. Or there might be someone that already programmed "a helper application or script which takes everything output, parses it, modifies it and then outputs it as you want". I guess that is the whole point of having a Q&A site. I am taking the opportunity to ask this, and someone knowledgeable may take the opportunity to answer. I have seen (and answered) quite a few questions of "the same kind". And the OP were quite grateful. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:01
  • If you were asking for "a helper application or script which takes everything output, parses it, modifies it and then outputs it as you want", your question would be off topic because as you should be aware `Seeking recommendations for books, tools, software libraries, and more` are off topic, i.e. not suited for Stack Overflow. It appears that you're just making a code or software request, and not actually seeking assistance with a specific reproducible issue with your provided code. If you wanted a setting in PowerShell to 'correct' the output, it would be an off topic software question. – Compo Jul 10 '20 at 15:05
  • @Compo - As you now mention, and others as well, I will expand the question to show the output I am seeing, which I consider having excess newlines. As for the rest, I am still puzzled and I wouldn't know even how to follow up on the conversation... I will do my best to clarify. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:13
  • @boxdog - I have updated the OP, hopefully you now see what I mean. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:35
  • @Lee_Dailey - Please see updated OP. I hope that shows what I mean. I am now trying to alter the output of various commands. It seems to me that PS has a generalized philosophy in its default way of outputting. I wonder whether that is configurable, or manageable in some form. PS: I am aware of the essential difference of a text-based piping of output/input (Unix) vs. object-based piping (PS). It is a very interesting topic. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:41
  • @AdminOfThings - Your comment works fine, partially. It removes leading and trailing newlines. Newlines in-between are still there. Would you know if there is a way to enforce such behaviour by default, at least for builtin commands? – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:46
  • @Bill_Stewart - I am not worried. I am simply looking for a different type of representation of those objects, and whether it is possible to set that as a preference. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:48
  • @Compo - I have expanded the OP. I hope it illustrates what I am referring to. I draw a parallel with the possible output of a compilation line with gcc. One can configure the verbosity in its output. And one can configure it at the compilation line (so one has to repeat it, or transfer it across makefiles or cmake files), or adding environment variables to make it the default. This *might* have a corresponding way of configuring output in PS. I cannot give too many details about what I do not know in the first place. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:53
  • @AdminOfThings - What you propose is this answer... https://stackoverflow.com/a/32253197/2707864 , which I had tried before. It is similar to https://stackoverflow.com/a/47454161/2707864 – sancho.s ReinstateMonicaCellio Jul 10 '20 at 15:57
  • To get the exact output you want, write a function that produces your desired output. – Bill_Stewart Jul 10 '20 at 16:13
  • @Bill_Stewart - Please see the answer added. That provides the intended functionality. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 16:18
  • @Compo - I guess I was unfairly tagged by you as sort-of-lazy. And I guess the answer provided shows: 1) Someone saw it was meaningful. 2) It had (at least one) concise answer. 3) The answer was not obvious (which is certainly a subjective appreciation). – sancho.s ReinstateMonicaCellio Jul 10 '20 at 16:23
  • @sancho.sReinstateMonicaCellio - thank you for the added info. i see that `mklement0` has pointed out how to modify the _displayed layout_. glad to see that you got your fix! [*grin*] – Lee_Dailey Jul 10 '20 at 16:35
  • Yes, aware of `Out-Default` - just be aware that it affects everything. (I would not prefer that, personally, but if you like it, enjoy.) – Bill_Stewart Jul 10 '20 at 19:16

1 Answers1

4

You can define a custom Out-Default function that removes all empty/blank lines from the output (for display only):

function Out-Default { 
  $Input | Out-String -Stream | Where { $_.Trim().Length -gt 0 } | Write-Host
}

You can place it in your $PROFILE file to be available in all future sessions (except those where PowerShell is invoked with -NoProfile).

All commands implicitly use this function for to-host (console) output, because Out-Default is a special command that PowerShell calls behind the scenes for handling to-host output (that is, for output that is neither captured nor piped nor redirected).

Therefore, once the function has been defined, simply calling Get-ChildItem (which is aliased to dir), for instance, should produce output with all empty/blanks removed.

Note that capturing / piping / redirecting output is not affected, as is desirable.

Caveat: As stated, Out-Default only affects to-host output, not also the behavior of other formatting system-based Out-* cmdlets, which you'd have to redefine separately, if desired.

Notably, a redefined Out-Default does not affect Out-File and its effective aliases > / >> - see the bottom section for a custom Out-File implementation that performs the same stripping of blank lines.


As an aside: PowerShell comes with a default Out-Default command, implemented as a cmdlet. While you can call Out-Default directly (whether the default implementation or a custom one), there is no reason to, and doing so should be avoided - see this answer.


As Compo points out, you can use the same technique ad hoc, for a given command; e.g.:

Get-ChildItem | Out-String -Stream | Where { $_.Trim().Length -gt 0 }

Note, however, that - unlike the Out-Default approach - this technique is suitable for display only, because you're then outputting string representations rather than the original objects (and if you were to pipe to Write-Host, you would bypass the (success) output stream altogether).


Custom Out-File function that also strips empty/blank lines and is also called by > / >>:

Note:

  • This function is more complex than the custom Out-Default function, because it needs to support the same parameters as the original cmdlet.

  • It will be noticeably slower than the original Out-File / > / >>, and it doesn't support the common -Confirm and -WhatIf parameters (which are rarely used with Out-File, however).

  • As printed below, the function is designed for use in PowerShell [Core] v6+ - see the comments in the source code for how to (easily) adapt it to Windows PowerShell.

# Note: Supports neither -Confirm nor -WhatIf
function Out-File {
  [CmdletBinding(DefaultParameterSetName = 'ByPath', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2096621')]
  param(
    [Parameter(ParameterSetName = 'ByPath', Mandatory, Position = 0)]
    [Alias('Path')]
    [string] $FilePath,
  
    [Parameter(ParameterSetName = 'ByLiteralPath', Mandatory, ValueFromPipelineByPropertyName)]
    [Alias('PSPath', 'LP')]
    [string]
    $LiteralPath,
  
    [Parameter(Position = 1)]
    # Note: This validation set is for PowerShell *Core* (v6+).
    # For Windows PowerShell support, comment out the the next line and uncomment the one after.
    [ValidateSet('ascii','bigendianutf32','unicode','utf8','utf8NoBOM','bigendianunicode','oem','utf7','utf8BOM','utf32')]
    # [ValidateSet('default', 'ascii','bigendianutf32','unicode','utf8','bigendianunicode','oem','utf7','utf32')]
    [string] $Encoding,
  
    [switch] $Append,
  
    [switch] $Force,
  
    [Alias('NoOverwrite')]
    [switch] $NoClobber,
  
    [ValidateRange(2, 2147483647)]
    [int] $Width,
  
    [switch] $NoNewline,
  
    [Parameter(ValueFromPipeline = $true)]
    [psobject] $InputObject
  )
  
  $null = $PSBoundParameters.Remove('InputObject')

  $Input | Out-String -Stream | Where-Object { $_.Trim().Length -gt 0 } | 
    Microsoft.PowerShell.Utility\Out-File @PSBoundParameters

}
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Interesting point... When I redirect output with, e.g., `Get-Module -ListAvailable > modules.txt`, extra newlines do not get trimmed. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 21:27
  • https://jdhitsolutions.com/blog/powershell/3025/scrub-up-powershell-content/ might be of interest here. Still have to understand a lot about PS... – sancho.s ReinstateMonicaCellio Jul 10 '20 at 21:45
  • Interesting point #2... I have added your function at the top of my `profile.ps1` and it works great. Now I added `$Host` a few lines below, launched a new console, and the output of `$Host` does not have the newlines trimmed. – sancho.s ReinstateMonicaCellio Jul 10 '20 at 21:53
  • @sancho.sReinstateMonicaCellio: That was my bad: as the answer states, `Out-Default` only covers to-_host_ output; `>`, which is an effective alias of `Out-File`, is _not_ affected (and neither are other `Out-*` cmdlets, such as `Out-String`); in short: you'd have to write a wrapper for `Out-File` as well; though it looks if you want `>` / `>>` to respect that too, you'll have to write a proxy (wrapper) function - see [this answer](https://stackoverflow.com/a/55539863/45375). – mklement0 Jul 10 '20 at 22:36
  • Well, that's what I see. The facts: 1) `profile.ps1` is being executed (I see the result of commands in it), 2) `Out-Default` is above `$Host` in `profile.ps1`, 3) the output of `$Host` has the "usual" newlines, 4) if I execute `$Host` at teh command prompt after startup, the newlines (in `$Host` and all other cmdlets) are gone. – sancho.s ReinstateMonicaCellio Jul 11 '20 at 11:55
  • @sancho.sReinstateMonicaCellio I see: the reason is that what the profile being loaded outputs is not yet subject to the `Out-Default` redefinition inside the profile. While generally not a good idea, in this case you could work around the problem with an explicit `Out-Default` call inside the profile: `$Host | Out-Default`. – mklement0 Jul 11 '20 at 13:52
  • So the redefinition of `Out-Default` takes place only when `profile.ps1` is finished? That is strange... – sancho.s ReinstateMonicaCellio Jul 11 '20 at 14:48
  • @sancho.sReinstateMonicaCellio: I suspect that PowerShell locks in the `Out-Default` command to use _before_ executing a pipeline. You can simulate how PowerShell loads your profile with the following command (assuming you haven't redefined `Out-Default` yet), which exhibits the same behavior: `. { function Out-Default { $Input | Out-String -Stream | Where { $_.Trim().Length -gt 0 } | Write-Host }; $Host }` - again, the redefined `Out-String` function has not yet taken effect for the script block's output, but does for all subsequent commands. – mklement0 Jul 11 '20 at 18:40
  • @sancho.sReinstateMonicaCellio: I've bitten the bullet and have written a custom `Out-File` function that is also used by `>` and `>>` - please see the bottom section. – mklement0 Jul 11 '20 at 19:01
  • 1
    I will try this and get back whenever I have anything worth commenting. This code goes well beyond my most elementary knowledge on PS. – sancho.s ReinstateMonicaCellio Jul 11 '20 at 19:06
  • Code posted at the top has some problems, see [this comment](https://stackoverflow.com/questions/62993334/powershell-new-commandwrapper-supply-values-for-the-following-parameters#comment111577624_63014560) and [this comment](https://stackoverflow.com/questions/63013113/powershell-debug-execution#comment111577524_63013113). Perhaps using `New-CommandWrapper` for `Out-Default` instead of `function` (which would possibly imply two nested such uses considering module `PSColor`) works. It might not be relevant the order in which nesting takes place. I wouldn't know how to implement it. – sancho.s ReinstateMonicaCellio Jul 26 '20 at 08:32
  • @sancho.sReinstateMonicaCellio I don't have the full picture, but you cannot override `Out-Default` multiple times. I wouldn't know how to implement `Out-Default` as a [proxy (wrapper) function](https://stackoverflow.com/a/55539863/45375), because you cannot stringify input objects _individually_ without changing the overall output format. Another way to get colored output is to write your own formatting instructions; start with `Get-FormatData -PowerShellVersion $PSVersionTable.PSVersion System.IO.DirectoryInfo | Export-FormatData -Path fd.xml` – mklement0 Jul 26 '20 at 12:47
  • I replaced line `$steppablePipeline.Process($_)` in `PSColor.psm1` with `$steppablePipeline.Process($_) | Out-String -Stream | Where { $_.Trim().Length -gt 0 } | Write-Host` Why would this not work? Any ideas how to do it right? – sancho.s ReinstateMonicaCellio Jul 26 '20 at 14:07
  • @sancho.sReinstateMonicaCellio As stated, you cannot solve this problem at the level of individual output objects - `Out-*` cmdlets need to consider all input objects together. Personally, I don't know a way around this. – mklement0 Jul 26 '20 at 15:15