0

Hi I'm a newbie in Powershell scripting.. I just wrote a simple function to detect if a file existed called isMarked() which takes the argument of file path string and return true/false.

function isMarked{
param($mark_name)
return Test-Path "$mark_name"
}

I tried and this function works correctly. However, a weird result occurred when I tried to use the logical operator to combine the results.

if(isMarked(".test") -and !(isMarked(".another_test")))

where when I tried individually,

isMarked(".test") returns True 
isMarked(".another_test") returns True

But when I combined the logical expression

(isMarked(".test") -and !(isMarked(".another_test"))

which should be False, it gives me a "True".....

I'm not sure what goes wrong. Any suggestions?

Thanks

  • 4
    At least, in PowerShell you should *not* place your arguments in brackets, the correct syntax is: `(isMarked ".test")-and !(isMarked ".another_test")` – iRon Jan 31 '21 at 10:43
  • Why shouldn't someone place arguments in parentheses? That doesn't matter. The issue here is that PowerShell interprets the `-and` operator as a parameter. Parameters have the same syntax as operators `-`. You just need to enclose your first command in parentheses as well (preferred with a leading `$`). For better readability place a space between command name and arguments, or even better, `use named parameters` --> `(isMarked -mark_name ('C:\temp\test.log')) -and !(isMarked -mark_name ('C:\temp\test.log2'))` – swbbl Jan 31 '21 at 10:51
  • 1
    @pwnosh _"That doesn't matter"_ ?? See [this answer](https://stackoverflow.com/a/11061342/9898643). – Theo Jan 31 '21 at 11:35
  • Anything following a _command-name_ will be parsed in [argument mode](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing) - thus treating `-and` as a parameter – Mathias R. Jessen Jan 31 '21 at 12:12
  • as @iRon pointed out, you have fallen for one of the classic gotchas when defining a BASIC function [as opposed to an advanced func]. those `()` around the parameters are WRONG. [*grin*] take a look at what you get when you remove them like this ... >>> `isMarked ".test"` << – Lee_Dailey Jan 31 '21 at 14:17
  • @Theo I'm sorry. My statement was not clear enough. It shouldn't mean that we can enclose ALL parameters between one pair of parentheses. My example above should show what I meant (i put each input in parentheses; not subexpressions or else). If we couldn't use parentheses like this, so many scripts would fail already. The issue here is just that the operator was interpreted as parameter. – swbbl Jan 31 '21 at 15:12
  • 1
    Just to provide one example to my previous answer, even when it's not a common PS style: `Get-ChildItem('C:\temp')('*.log')` works the same as `Get-ChildItem -Path 'C:\temp' -Filter '*.log'` – swbbl Jan 31 '21 at 15:34
  • Thank you all fellas for pointing out the parenthesis problem. Like I mentioned previously I'm a .net programmer that is a total newbie in PowerShell scripting. Will keep it in mind in the future. Thanks for the advice. :-) – squirrel_tw Jan 31 '21 at 20:29
  • one more question: if the input argument is an result of another function, I should write something like this : `isMarked $(anotherFunction)` . Is that correct? – squirrel_tw Jan 31 '21 at 20:35

1 Answers1

2

Reason for this is that the 2 sides being compared must be values. If you have expressions that need to be evaluated first before the comparison you need to surround them with parentheses. You have done this with your 2nd expression but have omitted to do so with your first.

Try instead

( isMarked(".test") ) -and !( isMarked(".another_test"))

or as other have stated in comments

(isMarked ".test") -and !(isMarked ".another_test") 

Either way will work. Placing the arguments inside parenthesis is not the problem here as stated in some of the comments.

Daniel
  • 4,792
  • 2
  • 7
  • 20
  • To complement: As mentioned in the comments already. Each argument must be surrounded with separated parentheses. Don't enclose multiple arguments which relates to different parameters in the same pair. Correct: `Some-Command ('ABC') ('DEF')` -- Wrong: `Some-Command('ABC','DEF')` – swbbl Jan 31 '21 at 16:04
  • I believe this works only because the parenthesis are acting as a separators, essentially the same as whitespace. – Daniel Jan 31 '21 at 16:52
  • Yes and No. You have to deep dive into the process of the PowerShell parser process (AST; "Abstract Syntax Tree") if you want to understand the background a bit. – swbbl Jan 31 '21 at 16:56