[powershell] What's the better (cleaner) way to ignore output in PowerShell?

Let's say you have a method or a cmdlet that returns something, but you don't want to use it and you don't want to output it. I found these two ways:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

What do you use? Which is the better/cleaner approach? Why?

This question is related to powershell null void

The answer is


I would consider using something like:

function GetList
{
  . {
     $a = new-object Collections.ArrayList
     $a.Add(5)
     $a.Add('next 5')
  } | Out-Null
  $a
}
$x = GetList

Output from $a.Add is not returned -- that holds for all $a.Add method calls. Otherwise you would need to prepend [void] before each the call.

In simple cases I would go with [void]$a.Add because it is quite clear that output will not be used and is discarded.


There is also the Out-Null cmdlet, which you can use in a pipeline, for example, Add-Item | Out-Null.

Manual page for Out-Null

NAME
    Out-Null

SYNOPSIS
    Deletes output instead of sending it to the console.


SYNTAX
    Out-Null [-inputObject <psobject>] [<CommonParameters>]


DETAILED DESCRIPTION
    The Out-Null cmdlet sends output to NULL, in effect, deleting it.


RELATED LINKS
    Out-Printer
    Out-Host
    Out-File
    Out-String
    Out-Default

REMARKS
     For more information, type: "get-help Out-Null -detailed".
     For technical information, type: "get-help Out-Null -full".

I realize this is an old thread, but for those taking @JasonMArcher's accepted answer above as fact, I'm surprised it has not been corrected many of us have known for years it is actually the PIPELINE adding the delay and NOTHING to do with whether it is Out-Null or not. In fact, if you run the tests below you will quickly see that the same "faster" casting to [void] and $void= that for years we all used thinking it was faster, are actually JUST AS SLOW and in fact VERY SLOW when you add ANY pipelining whatsoever. In other words, as soon as you pipe to anything, the whole rule of not using out-null goes into the trash.

Proof, the last 3 tests in the list below. The horrible Out-null was 32339.3792 milliseconds, but wait - how much faster was casting to [void]? 34121.9251 ms?!? WTF? These are REAL #s on my system, casting to VOID was actually SLOWER. How about =$null? 34217.685ms.....still friggin SLOWER! So, as the last three simple tests show, the Out-Null is actually FASTER in many cases when the pipeline is already in use.

So, why is this? Simple. It is and always was 100% a hallucination that piping to Out-Null was slower. It is however that PIPING TO ANYTHING is slower, and didn't we kind of already know that through basic logic? We just may not have know HOW MUCH slower, but these tests sure tell a story about the cost of using the pipeline if you can avoid it. And, we were not really 100% wrong because there is a very SMALL number of true scenarios where out-null is evil. When? When adding Out-Null is adding the ONLY pipeline activity. In other words....the reason a simple command like $(1..1000) | Out-Null as shown above showed true.

If you simply add an additional pipe to Out-String to every test above, the #s change radically (or just paste the ones below) and as you can see for yourself, the Out-Null actually becomes FASTER in many cases:

$GetProcess = Get-Process

# Batch 1 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Out-Null 
} 
}).TotalMilliseconds

# Batch 1 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess) 
} 
}).TotalMilliseconds

# Batch 1 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess 
} 
}).TotalMilliseconds

# Batch 2 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Select-Object -Property ProcessName | Out-Null 
} 
}).TotalMilliseconds

# Batch 2 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Select-Object -Property ProcessName ) 
} 
}).TotalMilliseconds

# Batch 2 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Select-Object -Property ProcessName 
} 
}).TotalMilliseconds

# Batch 3 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name | Out-Null 
} 
}).TotalMilliseconds

# Batch 3 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name ) 
} 
}).TotalMilliseconds

# Batch 3 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name 
} 
}).TotalMilliseconds

# Batch 4 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Out-String | Out-Null 
} 
}).TotalMilliseconds

# Batch 4 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Out-String ) 
} 
}).TotalMilliseconds

# Batch 4 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Out-String 
} 
}).TotalMilliseconds

Personally, I use ... | Out-Null because, as others have commented, that looks like the more "PowerShellish" approach compared to ... > $null and [void] .... $null = ... is exploiting a specific automatic variable and can be easy to overlook, whereas the other methods make it obvious with additional syntax that you intend to discard the output of an expression. Because ... | Out-Null and ... > $null come at the end of the expression I think they effectively communicate "take everything we've done up to this point and throw it away", plus you can comment them out easier for debugging purposes (e.g. ... # | Out-Null), compared to putting $null = or [void] before the expression to determine what happens after executing it.

Let's look at a different benchmark, though: not the amount of time it takes to execute each option, but the amount of time it takes to figure out what each option does. Having worked in environments with colleagues who were not experienced with PowerShell or even scripting at all, I tend to try to write my scripts in a way that someone coming along years later that might not even understand the language they're looking at can have a fighting chance at figuring out what it's doing since they might be in a position of having to support or replace it. This has never occurred to me as a reason to use one method over the others until now, but imagine you're in that position and you use the help command or your favorite search engine to try to find out what Out-Null does. You get a useful result immediately, right? Now try to do the same with [void] and $null =. Not so easy, is it?

Granted, suppressing the output of a value is a pretty minor detail compared to understanding the overall logic of a script, and you can only try to "dumb down" your code so much before you're trading your ability to write good code for a novice's ability to read...not-so-good code. My point is, it's possible that some who are fluent in PowerShell aren't even familiar with [void], $null =, etc., and just because those may execute faster or take less keystrokes to type, doesn't mean they're the best way to do what you're trying to do, and just because a language gives you quirky syntax doesn't mean you should use it instead of something clearer and better-known.*

* I am presuming that Out-Null is clear and well-known, which I don't know to be $true. Whichever option you feel is clearest and most accessible to future readers and editors of your code (yourself included), regardless of time-to-type or time-to-execute, that's the option I'm recommending you use.


Examples related to powershell

Why powershell does not run Angular commands? How do I install the Nuget provider for PowerShell on a unconnected machine so I can install a nuget package from the PS command line? How to print environment variables to the console in PowerShell? Check if a string is not NULL or EMPTY The term 'ng' is not recognized as the name of a cmdlet VSCode Change Default Terminal 'Connect-MsolService' is not recognized as the name of a cmdlet Powershell Invoke-WebRequest Fails with SSL/TLS Secure Channel Install-Module : The term 'Install-Module' is not recognized as the name of a cmdlet Change directory in PowerShell

Examples related to null

getElementById in React Filter values only if not null using lambda in Java8 Why use Optional.of over Optional.ofNullable? How to resolve TypeError: Cannot convert undefined or null to object Check if returned value is not null and if so assign it, in one line, with one method call How do I assign a null value to a variable in PowerShell? Using COALESCE to handle NULL values in PostgreSQL How to check a Long for null in java Check if AJAX response data is empty/blank/null/undefined/0 Best way to check for "empty or null value"

Examples related to void

Java 8 lambda Void argument how does int main() and void main() work How do I mock a static method that returns void with PowerMock? int main() vs void main() in C Returning from a void function What does void do in java? What's the better (cleaner) way to ignore output in PowerShell? How to mock void methods with Mockito What does "javascript:void(0)" mean? What does the return keyword do in a void method in Java?