Use a function:
function doOrEcho() {
$cmdLine = $args
if ($MY_DEBUG_FLAG) { # echo
"$cmdLine"
} else { # execute
# Split into command (excecutable) and arguments
$cmd, $cmdArgs = $cmdLine
if ($cmdArgs) {
& $cmd $cmdArgs
} else {
& $cmd
}
}
}
Then invoke it as follows:
doOrEcho my_dangerous_command args
Limitations:
Only works with calls to external programs, not to PowerShell cmdlets or functions (because you cannot relay named arguments - e.g. -Path .
- that way).[1]
- Passing the elements of an array (
$cmdArgs
) to an external program as individual arguments is a PowerShell technique called splatting; see this answer for more information, which also notes the general caveat that an empty string cannot be passed as an argument as-is in PowerShell versions up to 7.2.x, wether passed directly or as part of an array used for splatting.
As in your Bash solution, the echoed command will not reflect the original and/or necessary quoting for expanded arguments, so argument boundaries may be lost.
- However, it wouldn't be too hard to reconstruct at least an equivalent command line that works syntactically and shows the original argument boundaries.
To demonstrate it (using a call to the ls
Unix utility in 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.
Kory Gill points out that PowerShell has the -WhatIf
common parameter whose purpose is to preview operations without actually performing them.
However, -WhatIf
is not the right solution for the task at hand:
Only cmdlets and advanced functions can implement this parameter (based on functionality provided by PowerShell) - doing so requires quite a bit more effort than the simple function above.
The intent behind -WhatIf
is to show what data the command will operate on / what changes it will make to the system, whereas the intent behind the function above is to echo the command itself.
- For instance,
Remove-Item foo.txt -WhatIf
would show something like this:
What if: Performing operation "Remove File" on Target "C:\tmp\foo.txt".
While you could technically still use -WhatIf
in this use case, you'd then either have to use -WhatIf
ad hoc to turn on echoing (doOrEcho -WhatIf ...
) or set the $WhatIfPreference
preference variable to $true
- but doing so would then affect all cmdlets and functions that support -WhatIf
while the variable is set; additionally, -WhatIf
output is wordy, as shown above.
Arguably, it is Invoke-Command
, PowerShell's generic command-invocation cmdlet, that should support -WhatIf
as in the function above, but it doesn't.
[1] PowerShell has built-in magic to allow relaying even named arguments, but that only works when splatting the automatic $args
variable as a whole, i.e. with @args
.