Используйте функцию :
function doOrEcho() {
$cmdLine = $Args
if ($MY_DEBUG_FLAG) { # echo
"$cmdLine"
} else { # execute
# Split into command (excecutable) and arguments
$cmd, [string[]] $cmdArgs = $cmdLine
if ($cmdArgs) {
& $cmd @cmdArgs
} else {
& $cmd
}
}
}
Затем вызовите его следующим образом:
doOrEcho my_dangerous_command args
Ограничения :
Работает только с вызовами внешних программ , но не с командлетами или функциями PowerShell.
- См. Нижний раздел для предостережения о передаче пустой строки в качестве аргумента и о том, как сплаттинг используется для передачи аргументов.
Как и в вашем решении Bash, команда echoed будет не отражать оригинальное и / или необходимое цитирование для расширенных аргументов , поэтому границы аргументов может быть потеряно.
Чтобы продемонстрировать это (используя вызов утилиты ls
Unix в PowerShell Core):
# Default behavior: *execute* the command.
PS> doOrEcho ls -1 $HOME
# ... listing of files in $HOME folder, 1 item per line.
# With debug flag set: only *echo* the command, with arguments *expanded*
PS> $MY_DEBUG_FLAG = $true; doOrEcho ls -1 $HOME
ls -1 /home/jdoe # e.g.
Кори Джилл указывает, что PowerShell имеет -WhatIf
общий параметр , цель которого - предварительный просмотр операций без их фактического выполнения.
Однако -WhatIf
не является правильным решением для поставленной задачи:
Этот параметр могут реализовывать только командлеты и расширенные функции (в зависимости от функциональности, предоставляемой PowerShell) - для этого требуется немного больше усилий, чем для простой функции, описанной выше.
Цель -WhatIf
- показать, какие данные команда будет работать / какие изменения она внесет в систему, тогда как цель функции выше эхо самой команды .
- Например,
Remove-Item foo.txt -WhatIf
будет показывать что-то вроде этого:
What if: Performing operation "Remove File" on Target "C:\tmp\foo.txt".
Хотя технически вы все еще можете использовать -WhatIf
в этом случае, вам придется либо использовать -WhatIf
ad hoc, чтобы включить эхо (doOrEcho -WhatIf ...
), либо установить переменную предпочтения $WhatIfPreference
на $true
- но тогда это повлияет на все командлеты и функции, которые поддерживают -WhatIf
, пока переменная установлена; кроме того, -WhatIf
вывод является многословным, как показано выше.
Возможно, это Invoke-Command
, общий командлет вызова команд PowerShell, который должен поддерживать -WhatIf
, как в функции выше, но это не так.
Необязательное чтение: передача аргументов на основе массива или сплат во внешние программы
Splatting - это метод, который позволяет передавать аргументы команде через хеш-таблицу или массив, хранящийся в переменной, на которую вы затем ссылаетесь с помощью @
вместо $
при передаче его в качестве аргумента.
Для внешних программ имеет смысл только метод массив и, за одним исключением, вы можете даже передать массив как есть - $argumentArray
@argumentArray
- для достижения того же эффекта.
Это исключение - специальный символ остановки разбора , --%
, который говорит PowerShell не анализировать оставшиеся аргументы, как обычно, и вместо этого передавать их как есть - нерасширяемый, за исключением расширения cmd.exe
ссылки на переменные в стиле, такие как `% USERNAME%.
Только синтаксис (@argumentArray
) распознает символ --%
.
Однако с синтаксисом - $argumentArray
или @argumentArray
- аргумент, представляющий собой пустую строку (например, ''
или ""
), равен , а не правильно прошел через , потому что PowerShell просто удаляет его, что может нарушить команду.
Однако это также происходит с передачей аргументов direct и является неотъемлемым ограничением PowerShell для Windows PowerShell v5.1 / PowerShell Core 6.2.0 (см. эту проблему GitHub ).
Например, следующая команда работает с bash
, но выходит из PowerShell из-за строки с пустым аргументом:
# Bash
$ bash -c 'echo $#; echo /$1/' '' one # '' becomes $0, 'one' becomes $1
1
/one/ # OK
# PowerShell (Core)
PS> bash -c 'echo $#; echo /$1/' '' one
0
// # !! The '' was removed, so that 'one' was interpreted as $0