In PowerShell, syntax for if is as so:
if (<test1>)
{<statement list 1>}
[elseif (<test2>)
{<statement list 2>}]
[else
{<statement list 3>}]
Another syntax rule is that for subexpressions, you need to use parentheses like this:
write-output (get-date)
So with these two rules combined, I would expect that the test for some path needs to be written with two sets of parentheses like this:
if ((Test-Path ...)) {
# do something
}
However, this also works:
if (Test-Path ...) {
# do something
}
and just for the sake of completeness, this doesn’t work:
if (!Test-Path ...) {
# do something
}
(here, you would need to wrap the subexpression in parenthesis as usual).
Can anyone explain the syntax rules that apply here and how comes that I can use the IF test with one parenthesis only? Is it some PowerShell magic or am I misunderstanding the basic syntax rules?
Referring to C.2.2 from Appendix C: The PowerShell grammar in Bruce Payette’s Windows PowerShell in Action, we have:
This indicates the
(and)tokens as part of the literal syntax for recognizing anifstatement, and that the<test>from theabout_Ifdocumentation refers to a pipeline that will be resolved to a Boolean.Following the pipeline rules, we find:
Test-Path ...parses to a<cmdletCall>of<name> <parameterArgumentToken>,!Test-Path ...results in an<expressionRule>of<UnaryOperatorToken> <propertyOrArrayReferenceRule>, which fails when the cmdlet call cannot match the simple property or array rule, whereas!(Test-Path ...)is able to match the parenthesized cmdlet call as a sub-expression.Edit: See also PowerShell 2.0 Language Specification (thanks to Roman’s answer to another question).