If you have multiple parameters which require a value when calling a command or a script, I know you can pass it like this:
$parameters = @{
name = "John"
last_name = "Doe"
}
But if the command or script actually just expect -T
to indicate something like a flag, but the parameter itself doesn't require a value. How can I set that in a variable?
$optionalT = ""
if ($itNeedsTheT) $optionalT = "-T"
command $optionalT
If I do it like that it complains with the following message:
Unknown argument 'T' on command line.
tl;dr
# Pass the $itNeedsTheT Boolean - which indicates whether the -T switch should
# be passed - as the switch's *value*.
command -T:$itNeedsTheT
If $itNeedsTheT
is $false
, the above is the same as omitting -T
- usually (read on for details).
Note the need to use :
to separate the switch name from the value.
As boxdog points out in a comment, in a hashtable used with splatting (@parameters
), you use a Boolean value to represent a switch parameter (a flag-like parameter of type [switch]
) .
# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true
# Define the hashtable for splatting...
$parameters = @{
Path = '.'
Recurse = $recurseIfTrue # turn the -Recurse switch on or off
}
# ... and pass it to the target command.
# *Loosely speaking*, the following command is the same as either:
# Get-ChildItem -Path '.' -Recurse # if $recuseIfTrue was $true
# or:
# Get-ChildItem -Path '.' # if $recuseIfTrue was $false
Get-ChildItem @parameters
That is, loosely speaking:
$true
to pass the switch$false
to not pass the switch.This allows you to keep a single hashtable definition that unconditionally includes the switch parameter, but whose value can determine programmaticaly.
Caveat:
Strictly speaking, hashtable entry Recurse = $true
translates to parameter -Recurse:$true
and Recurse = $false
doesn't translate into omitting the parameter, it translates to passing -Recurse:$false
.
In most cases, omitting a switch -Foo
and passing it with value $false
- i.e. -Foo:$false
- are equivalent.
However, commands can detect the difference and sometimes act differently:
A notable example is the -Confirm
common (switch) parameter: omitting -Confirm
means that the $ConfirmPreference
preference variable is respected, whereas -Confirm:$false
means that the preference variable should be overridden (and confirmation should not be requested).
If you want to make this distinction yourself in a PowerShell script or function, you can call $PSBoundParameters.ContainsKey('Foo')
in addition to checking the $Foo
(-Foo
) switch parameter variable's value.
If you're dealing with such a command and you want to programmatically enforce omission of a switch parameter, you'll have no choice but to conditionally add an entry for this switch, in a separate step:
# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true
# A 'Recurse' key now can NOT be included unconditionally,
# if you want to *omit* -Recurse in case $recurseIfTrue is $false
$parameters = @{
Path = '.'
}
# Add a 'Recurse' entry only if the switch should be passed.
if ($recurseIfTrue) {
$parameters.Recurse = $true
}
Get-ChildItem @parameters
Finally, note that as an alternative to specifying a switch value programmatically via splatting, you can pass a dynamic value to a switch directly:
# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true
Get-ChildItem -Path . -Recurse:$recurseIfTrue
Note the need to use :
to separate the switch name from its value.
This is necessary, because using the customary whitespace to separate the parameter name from its value would cause PowerShell to interpret the Boolean as the next argument, given that switch parameters normally do not take values.
Although rarely used, this :
-based syntax works with all parameter types.