Как запустить несколько команд в одной строке в PowerShell?

В командной строке cmd вы можете запустить две команды в одной строке следующим образом:

ipconfig /release & ipconfig /renew

Когда я запускаю эту команду в PowerShell, я получаю:

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

Есть ли в PowerShell оператор, позволяющий быстро создать эквивалент & в подсказке cmd?

Подойдет любой способ запуска двух команд в одной строке. Я знаю, что могу сделать сценарий, но я ищу что-то еще более неуместное.

5 ответов

Решение

Используйте точку с запятой для объединения команд в PowerShell:

ipconfig /release; ipconfig /renew

В PowerShell 7 у нас есть Pipeline chain operators который позволяет вам добавлять условный элемент в ваши последовательные однострочные команды

Операторы:

  • && это запустит вторую команду, только если первая будет успешной.
  • || это запустит вторую команду, только если первая не сработает.

Примеры:

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

конечно, вы можете связать их еще больше, например x && y || z и т.п.

это также работает для старых команд, подобных cmd, таких как 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

Эти операторы используют символ $? и переменные $LASTEXITCODE для определения сбоя конвейера. Это позволяет использовать их с собственными командами, а не только с командлетами или функциями.

Источник: https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-70?view=powershell-7

Точка с запятой свяжет команды, как указано в предыдущем ответе, хотя есть ключевое отличие в поведении с & оператор в интерпретаторе команд в стиле MS-DOS.

В интерпретаторе команд подстановка переменных происходит при чтении строки. Это допускает некоторые полезные возможности, такие как обмен переменных без промежуточного:

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

В результате:

2
1

Насколько я знаю, в PowerShell нет способа воспроизвести это поведение. Некоторые могут утверждать, что это хорошо.

На самом деле есть способ сделать это в PowerShell:

$b, $a = $a, $b

Это приведет к замене значений переменной на одну строку.

Для PowerShell 5 (установка по умолчанию для компьютеров Windows в обозримом будущем) вы, конечно, можете использовать точку с запятой для разделения операторов, но все операторы будут выполняться по умолчанию, даже если один из них завершится неудачно. Лично я предпочитаю работать так, чтобы в случае сбоя в чем-то вся линия останавливалась в REPL, и я думаю, что многие другие люди делают то же самое.

$ErrorActionPreferenceпозволяет вам контролировать поведение того, что происходит, когда оператор терпит неудачу, но является непрерывающейся ошибкой (это большинство ошибок, включая ошибки, не найденные командой). Вы можете установить эту переменную$ErrorActionPreference="Stop"чтобы подражать поведению&&в Bash и PowerShell 7 для области действия этой переменной.

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

У меня возникли проблемы с поиском точной документации по этому поведению, но эта переменная, похоже, имеет динамическую область действия, поэтому вы можете временно переопределить ее в блоке, если не хотите устанавливать ее глобально.

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

Наконец, если вам нужно что-то повторно используемое, вы можете использовать эту функцию более высокого порядка.

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

Который затем используется следующим образом.

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

Обратите внимание, что в приведенных выше примерах «Здесь» не печатается, посколькуfakeCommandтерпит неудачу, поскольку это не настоящая команда.

Я протестировал код, представленный в этом решении, для PowerShell 5 и 7, и он должен быть полностью переносимым, по крайней мере, в Windows. Хотя PowerShell 7 должен быть очень похож на разных платформах, я не тестировал эти команды на Linux или MacOS.

      "C:\\msys64\\mingw64\\bin\\g++.exe -g3 -Wall \"${file}\" -o \"${fileDirname}\\${fileBasenameNoExtension}.exe\" ; &\"${fileDirname}\\${fileBasenameNoExtension}.exe\""

В PowerShell

Другие вопросы по тегам