Search code examples
powershellbooleanexit-code

Powershell equivalent of Linux true command


This stackoverflow answer explains what the Linux true command is. My question, does Powershell (v5/v6) offers also a true command?

I already googled around, used Get-help *true*, but could not find anything about it.

Thx


Solution

  • In short:

    • There is no PowerShell equivalent to the true and false Unix utilities.

    • Because PowerShell's conditionals and error handling work very differently than in POSIX-like shells such as bash, there is no need for them.

    The primary use of Unix utility true is to reset the exit code to 0 in situations where you deliberately want to ignore a previous command's failure (signaled via a nonzero exit code) in POSIX-like shells such as bash, such as in conditionals or with the abort-on-unhandled-failures option set -e in effect.
    Neither true nor its counterpart, false, produce any output - their sole purpose is to set an exit code.

    PowerShell doesn't use exit codes natively (though you can set them for the benefit of outside callers with exit <n>), and its conditionals do not act on them.

    • PowerShell's automatic $? variable is similar in the abstract to $? in POSIX-like shells, except that it reports a Boolean, whereas POSIX-like shells report the exit code; that is $? containing 0 in a POSIX-like shell is akin to $? containing $true in PowerShell.

    • PowerShell never acts on $? implicitly, but you can use it in PowerShell conditionals explicitly, so that the following two - contrived for simplicity - commands would be equivalent:

      # POSIX-like shells:
      # Event though the `ls` command fails `|| true` makes the overall
      # command succeed.
      if ls /nosuchfile || true; then echo success; fi
      
      # PowerShell:
      # `$?` would reflect `$false` after the failed `ls` command.
      # `$null = $null` is a dummy command that resets `$?` to `$true`
      # `$?` is then *output* for the `if` to test.
      if ($(ls /nosuchfile; $null = $null; $?)) { 'success' }
      

    While PowerShell has the automatic $true and $false variables (conceptually, constants), they are Boolean values used for comparison with output (data), not commands that set invisible status information (exit codes).

    Read on for background information.


    Conditionals in POSIX-like shells vs. in PowerShell

    In POSIX-like shells such as bash, conditionals operate on the exit codes of commands, i.e., (post-execution) status information, not their output.

    By contrast, PowerShell conditionals operate on command or expression output, i.e. data, not status information.

    In short:

    • Conditionals in POSIX-like shells act on invisible exit codes and pass success output (stdout output) through.

    • Conditionals in PowerShell act on success output and consume it in the process.

    Both shells pass error output (stderr) through.


    If you want a PowerShell conditional to act on a command's (post-execution) status (success vs. failure):

    You can use the automatic $? variable, whose behavior depends on whether the command at hand is a PowerShell-native one or an external program such as a Unix utility:

    • External programs: If the program's exit code is 0, $? reflects $true, otherwise $false

      • This is akin to the built-in $? variable in POSIX-like shells such as bash, except that $? there contains the actual exit code; that is, $? containing 0 in a POSIX-like shell is the same as $? containing $true in PowerShell after execution of an external program.

        • To get the actual exit code in PowerShell, use the automatic $LASTEXITCODE variable, which reflect's the exit code of the most recently executed external program (PowerShell-native commands generally do not set exit codes, though you can use exit <n> in scripts, primarily for reporting exit codes to outside callers).
    • PowerShell-native commands (cmdlets, functions, scripts): $? is $true if the command did not fail fundamentally and did not write to PowerShell's error stream (such as with Write-Error; note that stderr output from external programs by default does not write to PowerShell's error stream).

      • Note that $? therefore does not necessarily tell you whether a given command considered its overall execution successful or not; $? being $false merely tells you only that some error was reported.
      • However, you can wrap a command invocation in a try { ... } catch { ... } statement, which helps you distinguish non-terminating from terminating errors (by default only the latter trigger the catch block);

    Use of $? is not common in PowerShell, because failure is typically handled with the
    -ErrorAction common parameter / $ErrorActionPreference preference variable and/or try { ... } catch { ... } statements.

    That said, these methods cannot be used on external programs, where testing $? or $LASTEXITCODE is a must to detect failure.
    This GitHub discussion and this RFC draft call for better integration of external programs with PowerShell's error handling.

    For a comprehensive overview of PowerShell's error handling, see this GitHub issue.