J1raya
J1raya

Reputation: 340

Powershell issue with do while loop

I've got a simple bit of code that looks for a string in a series of log files.

If it finds the string, it should exit the loop (nested inside another loop as part of a function) with $buildlogsuccess = 'True'

If it can't find the string, it should exit and return $buildlogsuccess = 'False'

The select-string statement itself works, however it looks like there's something wrong with the below code:

        $logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
        $count = ($logArr).count
        Foreach ($log in $logArr) {
            Do {
            $count -= 1
            $buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
            If (($buildlogsuccess)) {break}
            } while ($count -gt '0')
        }

When one of the logs has the string, the loop finishes and should return $buildlogsuccess as 'True'.

If I check $log it shows the file that I know has the string (in this instance C:\build\Logs\Installer1.log).

Strangely, at this point $count shows as having a value of -1?

If I take the string out of that file and run again it also exits and returns the correct variable value (and shows the $log variable as the last file in $logArr as expected), but this time $count shows as -24.

My code is also returning $buildlogsuccess as 'False' when the string is present in one of the log files.

Re-tested [bool](select-string -path $log -simplematch $buildstring) by manually populating $log (with a file that has that string) and $buildstring and get 'True' as expected when using

[bool](select-string -path $log -simplematch $buildstring)

Note: Variables it uses:

$buildstring = "Package 'F:\xxx\Bootstrap\apackage\Installsomething.xml' processed successfully"

Any help identifying where I've gone wrong would be appreciated.

Upvotes: 1

Views: 1134

Answers (3)

mklement0
mklement0

Reputation: 437743

Your code can be greatly simplified:

$buildlogsuccess = Select-String -SimpleMatch -Quiet $buildstring C:\build\Logs\install*.log

The above assumes that there are no directories that match install*.log; if there's a chance of that, pipe the output of Get-ChildItem -File C:\build\Logs -Filter install*.log to Select-String instead.

Upvotes: 2

J1raya
J1raya

Reputation: 340

Thanks Norsk

I over-complicated for myself.

This worked:

        $logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
        $count = ($logArr).count
        Foreach ($log in $logArr) {
            $buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
            If ($buildlogsuccess) {break}
        }

Upvotes: 0

Norsk
Norsk

Reputation: 633

Do-while will first do the thing, then check the while statement. You're iterating over n files. It doesn't check the value of $count before it executes that portion.

So let's say the first file does not contain the string you're looking for. It will (correctly) decrement the $count variable to zero, and then it moves on to the next $log in $logArr.

Now for each next file in the folder it will decrement $count, and then exit the loop when it sees that $count is not greater than 0.

I don't know why you're using the do-while loop at all here

Upvotes: 1

Related Questions