Как запустить несколько команд в одной строке в 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 для определения сбоя конвейера. Это позволяет использовать их с собственными командами, а не только с командлетами или функциями.
Точка с запятой свяжет команды, как указано в предыдущем ответе, хотя есть ключевое отличие в поведении с &
оператор в интерпретаторе команд в стиле 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