434

In a cmd prompt, you can run two commands on one line like so:

ipconfig /release & ipconfig /renew

When I run this command in PowerShell, I get:

Ampersand not allowed. The `&` operator is reserved for future use

Does PowerShell have an operator that allows me to quickly produce the equivalent of & in a cmd prompt?

Any method of running two commands in one line will do. I know that I can make a script, but I'm looking for something a little more off the cuff.

3
612

Use a semicolon to chain commands in PowerShell:

ipconfig /release; ipconfig /renew
8
  • 13
    Will they run in parallel or sequentially?
    – Tarkus
    Jul 16 '14 at 1:13
  • 27
    This will run them sequentially, as does the & operator in cmd.exe.
    – Squeezy
    Jul 23 '14 at 5:38
  • 64
    There is big difference though - ";" runs the second command even if the first fails.
    – Ivan
    Oct 8 '14 at 16:50
  • 13
    As mentioned above, this is also the behavior of & in cmd.exe.
    – Squeezy
    Oct 8 '14 at 16:53
  • 11
    @Rafi Yes, Try {Command-One -ea Stop} Catch {Command-Two}
    – Dave_J
    Aug 5 '16 at 11:05
36

A semicolon will link the commands as the previous answer stated, although there is a key difference to the behaviour with the & operator in the MS-DOS style command interpreter.

In the command interpreter, the variable substitution takes place when the line is read. This allows some neat possibilities such as swapping variables without an interim:

set a=1
set b=2
set a=%b% & set b=%a%
echo %a%
echo %b%

Would result in:

2
1

As far as I know, there is no way to replicate this behaviour in PowerShell. Some may argue that's a good thing.

There is in fact a way to do this in PowerShell:

$b, $a = $a, $b

It will result in a single line swapping of the variable values.

1
  • Doesn't seem to work from "Target" field with -command option in shortcut though
    – clearlight
    Apr 6 '18 at 13:34
24

In PowerShell 7, we have Pipeline chain operators which allows you to add some conditional element to your sequential one-line commands

The operators are:

  • && this will run the second command only if the first one succeeds.
  • || this will run the second command only if the first one fails.

examples:

PS Z:\Powershell-Scripts> Write-Host "This will succeed" && Write-Host "So this will run too"
This will succeed
So this will run too

PS Z:\Powershell-Scripts> Write-Error "This is an error" && Write-Host "So this shouldn't run"
Write-Error "This is an error" && Write-Host "So this shouldn't run": This is an error

PS Z:\Powershell-Scripts> Write-Host "This will succeed" || Write-Host "This won't run"
This will succeed

PS Z:\Powershell-Scripts> Write-Error "This is an error" || Write-Host "That's why this runs"
Write-Error "This is an error" || Write-Host "That's why this runs": This is an error
That's why this runs

of course you can chain them even more together like x && y || z etc.

this also works for old cmd-like commands like ipconfig

PS Z:\Powershell-Scripts> ipconfig && Write-Error "abc" || ipconfig


Windows-IP-Konfiguration


Ethernet-Adapter Ethernet:

   Verbindungsspezifisches DNS-Suffix: xxx
   Verbindungslokale IPv6-Adresse  . : xxx
   IPv4-Adresse  . . . . . . . . . . : xxx
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . : xxx
ipconfig && Write-Error "abc" || ipconfig: abc

Windows-IP-Konfiguration


Ethernet-Adapter Ethernet:

   Verbindungsspezifisches DNS-Suffix: xxx
   Verbindungslokale IPv6-Adresse  . : xxx
   IPv4-Adresse  . . . . . . . . . . : xxx
   Subnetzmaske  . . . . . . . . . . : 255.255.255.0
   Standardgateway . . . . . . . . . : xxx

These operators use the $? and $LASTEXITCODE variables to determine if a pipeline failed. This allows you to use them with native commands and not just with cmdlets or functions.

Source: https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-70?view=powershell-7

6
  • Not working. I tried in powershell: vagrant destroy -f && vagrant up. Does not work.
    – Basil A
    Apr 9 '20 at 11:05
  • @BasilA did you try that in PowerShell 7, newest version? it's also possible that not-built-in commands like yours don't work.
    – SimonS
    Apr 9 '20 at 13:58
  • 1
    @BasilA The documentation says: "These operators use the $? and $LASTEXITCODE variables to determine if a pipeline failed. This allows you to use them with native commands and not just with cmdlets or functions." so you should check if your non native commands set these correctly
    – SimonS
    Apr 9 '20 at 14:09
  • Okay, will check it up. Thanks.
    – Basil A
    Apr 9 '20 at 15:18
  • 1
    @austinheiman 7.2 is the newest now I believe :-). However everything above PowerShell 5 is not shipped directly with Windows. You'll need to download it manually. It won't replace PowerShell 5, so you'll have both Versions.
    – SimonS
    Jan 14 at 10:31
4

For PowerShell 5 (default install for Windows machines for the foreseeable future), you can of course use a semicolon to separate statements, but all statements will be executed by default even if one fails. Personally, I prefer to run things so that if one thing fails the whole line stops in the REPL and I imagine a lot of other folks do as well.

$ErrorActionPreference lets you control the behavior of what happens when a statement fails but is a non-terminating error (which are most errors including command not found errors). You can set this variable $ErrorActionPreference="Stop" in order to emulate the behavior of && in Bash and PowerShell 7 for the scope of this variable.

$ErrorActionPreference="Stop"
# Line break
fakeCommand; echo "Here"

I have had trouble finding precise documentation for this behavior, but this variable seems to be dynamically scoped so you can override it in a block temporarily if you don't want to set it globally.

Invoke-Command -ScriptBlock {$ErrorActionPreference="Stop"; fakeCommand; echo "Here"}

Finally, if you want something reusable, you can use this higher order function.

function Run-Block-With-Error($block) {
    $ErrorActionPreference="Stop"
    Invoke-Command -ScriptBlock $block
}

Which is then used as follows.

Run-Block-With-Error {fakeCommand; echo "Here"}

Note in the examples above that "Here" is not printed since fakeCommand fails as it is not a real command.

I have tested the code provided in this solution for both PowerShell 5 and 7 and it should be fully portable, at least on Windows. While PowerShell 7 should be very similar on different platforms, I did not test these commands on Linux or MacOS.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.