44

There's already question addressing my issue (Can I get && to work in Powershell?), but with one difference. I need an OUTPUT from both commands. See, if I just run:

(command1 -arg1 -arg2) -and (command2 -arg1)

I won't see any output, but stderr messages. And, as expected, just typing:

command1 -arg1 -arg2 -and command2 -arg1 

Gives syntax error.

Community
  • 1
  • 1
Andy
  • 3,139
  • 4
  • 21
  • 13
  • 1
    A short-ciruiting OR will only execute the second expression if the first evals to false (fails). I suspect the OP wants the second expression to execute only if the first evals to true (succeeds) which a short-circuiting -and gives us. – Keith Hill Feb 14 '10 at 21:57
  • Whoever is interested in Bash-style `&&` and `||` becoming a part of PowerShell: please vote for the feature [here](https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11087898-implement-the-and-operators-that-bash-has). – mklement0 Jan 21 '17 at 19:12
  • Possible duplicate of [What are the PowerShell equivalent of Bash's && and || operators?](http://stackoverflow.com/questions/2416662/what-are-the-powershell-equivalent-of-bashs-and-operators) – mklement0 Jan 23 '17 at 21:46
  • Note: Despite this question's tile mentioning both `&&` and `||`, the body - and subsequently the answers - focus on `&&` only. A [closely related question](http://stackoverflow.com/q/2416662/45375) is more generic. – mklement0 Jan 23 '17 at 21:49
  • 1
    **June 2019 update**: PowerShell team are implementing `&&` and `||`! Weigh in at the [GitHub PR](https://github.com/PowerShell/PowerShell/pull/9849) – pilau Jun 12 '19 at 07:52

7 Answers7

43

2019: the Powershell team are considering adding support for && to Powershell - weigh in at this GitHub PR

Try this:

$(command -arg1 -arg2 | Out-Host;$?) -and $(command2 -arg1 | Out-Host;$?)

The $() is a subexpression allowing you to specify multiple statements within including a pipeline. Then execute the command and pipe to Out-Host so you can see it. The next statement (the actual output of the subexpression) should output $? i.e. the last command's success result.


The $? works fine for native commands (console exe's) but for cmdlets it leaves something to be desired. That is, $? only seems to return $false when a cmdlet encounters a terminating error. Seems like $? needs at least three states (failed, succeeded and partially succeeded). So if you're using cmdlets, this works better:

$(command -arg1 -arg2 -ev err | Out-Host;!$err) -and 
$(command -arg1 -ev err | Out-Host;!$err)

This kind of blows still. Perhaps something like this would be better:

function ExecuteUntilError([scriptblock[]]$Scriptblock)
{
    foreach ($sb in $scriptblock)
    {
        $prevErr = $error[0]
        . $sb
        if ($error[0] -ne $prevErr) { break }
    }
}

ExecuteUntilError {command -arg1 -arg2},{command2-arg1}
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • 1
    Thanks, Keith (BTW, I use PSCX and find it great, many thanks for those!). Though it seems pretty usable, there's a drawback comparing to UNIX pipeline. Consider the following: `command1 && command2 || command3`. It's pretty common pattern, I think. – Andy Feb 15 '10 at 06:09
  • 7
    Yeah, this is a bit of a hack compared to proper && and || support. – Keith Hill Feb 15 '10 at 06:46
  • 1
    Since (at least) PSv2, _non-terminating_ errors _do_ set `$?` to `$false`: for instance, `$null = Get-Item \, nosuch; $?` outputs `$false`. In the case of a _terminating_ error, the command line / script would abort altogether by default; if you do `try` / `catch` the error, `$?` is `$false` in the `catch` block, or, if the `catch` block is empty, immediately afterward; e.g., `try { throw "terminating err" } catch { }; $?` – mklement0 Jan 21 '17 at 17:23
  • 1
    The `ExecuteUntilError` function is handy, but please make it more obvious how much of a hack the `Out-Host` solution is, given that it bypasses the normal success output stream and therefore prevents sending the output through the pipeline or capturing it in a variable or file. – mklement0 Jan 21 '17 at 18:15
  • To paraphrase your statement about the need for 3 `$?` states: With cmdlets, `$?` allows you to distinguish only between "processing of all input items succeeded" and "processing of at least one, but possibly all input items failed"; in other words: you cannot distinguish between partial and complete failure; the workaround is to compare the input count to the change in `$Error.Count`. – mklement0 Jan 21 '17 at 18:17
7

Powershell 7 preview 5 has them. I don't know why this was deleted with no notification or explanation. https://devblogs.microsoft.com/powershell/powershell-7-preview-5/ This will give the output of both commands, as the question requested.

echo 'hello' && echo 'there'
hello
there

echo 'hello' || echo 'there'
hello
js2010
  • 23,033
  • 6
  • 64
  • 66
4

To simplify multistep scripts where doThis || exit 1 would be really useful, I use something like:

function ProceedOrExit { 
    if ($?) { echo "Proceed.." } else { echo "Script FAILED! Exiting.."; exit 1 } 
}

doThis; ProceedOrExit
doNext

# or for long doos
doThis
ProceedOrExit
doNext
dadhi
  • 4,807
  • 19
  • 25
3

Update: PowerShell [Core] 7.0 introduced && and || support - see this answer.


Bash's / cmd's && and || control operators have NO Windows PowerShell equivalents, and since you cannot define custom operators, there are no good workarounds.

  • The | Out-Host-based workaround in Keith Hill's answer is a severely limited in that it can only send normal command output to the console (terminal), preventing the output from being sent on through the pipeline or being captured in a variable or file.

Find background information in this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

Little longer way is see below

try {
  hostname
  if ($lastexitcode -eq 0) {
    ipconfig /all | findstr /i bios
  }
} catch {
  echo err
} finally {}
Michel de Ruiter
  • 7,131
  • 5
  • 49
  • 74
Cyberiron
  • 9
  • 1
  • There is no need for `try` / `catch`, because it is only needed for _terminating_ errors, which external utilities such as `hostname`, `ipconfig` and `findstr` cannot trigger. Checking `$LASTEXITCODE` is only needed if you want to know the specific exit code set by an external utility - abstract success or failure is reflected in `$?`, just as with native cmdlets. As an aside: please [format your code properly](http://meta.stackexchange.com/a/22189/248777). – mklement0 Jan 21 '17 at 17:54
1

The simplest solution is to use

powershell command1 && powershell command2

in a cmd shell. Of course, you can't use this in a .ps1 script, so there's that limitation.

cowlinator
  • 7,195
  • 6
  • 41
  • 61
  • 3
    @FrancescoMantovani, correct, but the `&&` here isn't in powershell, it's in a cmd shell. My answer here is to use cmd to string together 2 powershell commands (both with full output printed). – cowlinator Sep 14 '18 at 20:23
1

With Powershell 7.0 released, && and || are supported

https://devblogs.microsoft.com/powershell/announcing-powershell-7-0/

New operators:
  Ternary operator: a ? b : c
  Pipeline chain operators: || and &&
  Null coalescing operators: ?? and ??=
Sunbreak
  • 391
  • 3
  • 8