2

In the code below I can use the -and operator to make a compound if statement, but when using Test-Path with -and there is a syntax error.

What is the proper way to use -and with a command like Test-Path?

$a = 1
$b = 1
$c = 1
if ($a -eq $b -and $a -eq $c ) {
    write-host "Variables are equal."
}
$path1 = "C:\Windows"
$path2 = "C:\Users"
if (Test-Path $path1 -and Test-Path $path2) {
    write-host "paths exist."
}

2 Answers 2

3

If you put brackets around your usages of Test-Path then it works, i.e.

$path1 = "C:\Windows"
$path2 = "C:\Users"
if ((Test-Path $path1) -and (Test-Path $path2)) {
    write-host "paths exist."
}
Sign up to request clarification or add additional context in comments.

3 Comments

Is it a regional thing to call parenthesis brackets?
@AustinFrench more a case of having to type 9 chars instead of 11 ;) Although it would be better again to call them braces; only 6 chars.
@AustinFrench: Yes: Commonwealth countries (the UK and former colonies) use the term "brackets" for ( and ), whereas US English refers to these characters as "parentheses" (singular: "parenthesis").
2

DeanOC's helpful answer provides an effective solution.

As for why the parentheses (brackets) are needed:

PowerShell has two fundamental parsing modes:

  • argument mode, which works like traditional shells

  • expression mode, which works like traditional programming languages.

Running Get-help about_Parsing provides an introduction to these modes.

  • Test-Path $path1 and Test-Path $path2 in isolation are parsed in argument mode.

  • Operator -and can only be used in expression mode.

  • In order to use the output of the argument-mode Test-Path commands in expression mode, they must be enclosed in (...):

    • Use of (...) forces a new parsing context, and

    • the 1st token of a given parsing context determines whether it is parsed in argument or expression mode.


Another thing to consider is PowerShell's pervasive support for collections, which often allows you to operate at a higher level of abstraction:

$paths = "C:\Windows", "C:\Users" # define *array* of input paths
if ((Test-Path $paths) -notcontains $False) { # See if ALL paths exist.
  "ALL paths exist."
}
  • Test-Path accepts an array of paths to test, and outputs a corresponding array of Booleans indicating the respective existence.

  • Operator -notcontains tests non-membership in the LHS array; in other words: if no Boolean returned by Test-Path is $False, the implication is that all input paths exist.

  • Note that Write-Host was deliberately omitted, because in order to send something to PowerShell's success stream (the analog to stdout in traditional shells), you don't need an explicit output command at all, and, conversely, Write-Host actually bypasses the success stream - see this blog post.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.