Search code examples
powershellselect-string

Script lists all files that don't contain needed content


I'm trying to find all files in a dir, modified within the last 4 hours, that contain a string. I can't have the output show files that don't contain needed content. How do I change this so it only lists the filename and content found that matches the string, but not files that don't have that string? This is run as a windows shell command. The dir has a growing list of hundreds of files, and currently output looks like this:

File1.txt
File2.txt
File3.txt
... long long list, with none containing the needed string

(powershell "Set-Location -Path "E:\SDKLogs\Logs"; Get-Item *.* | Foreach { $lastupdatetime=$_.LastWriteTime; $nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 4) {Select-String -Path $_.Name -Pattern "'Found = 60.'"| Write-Host "$_.Name Found = 60";  }}")

I tried changing the location of the Write-Host but it's still printing all files.

Update: I'm currently working on this fix. Hopefully it's what people were alluding to in comments.

$updateTimeRange=(get-date).addhours(-4)
$fileNames = Get-ChildItem -Path "K:\NotFound" -Recurse -Include *.* 
foreach ($file in $filenames)
{
  #$content = Get-Content $_.FullName
  Write-host "$($file.LastWriteTime)"
  if($file.LastWriteTime -ge $($updateTimeRange))
  {
    #Write-Host $file.FullName
    if(Select-String -Path $file.FullName -Pattern 'Thread = 60')
    {
        Write-Host $file.FullName
    }
  }
}

Solution

  • If I understood you correctly, you just want to display the file name and the matched content? If so, the following will work for you:

    $date = (Get-Date).AddHours(-4) 
    Get-ChildItem -Path 'E:\SDKLogs\Logs' | Where-Object -FilterScript { $date -lt $_.LastWriteTime } |
        Select-String -Pattern 'Found = 60.' | 
        ForEach-Object -Process {
            '{0} {1}' -f $_.FileName, $_.Matches.Value
        }
    

    Get-Date doesn't need to be in a variable before your call but, it can become computationally expensive running a call to it again and again. Rather, just place it in a variable before your expression and call on the already created value of $date.

    Typically, and for best practice, you always want to filter as far left as possible in your command. In this case we swap your if statement for a Where-Object to filter as the objects are passed down the pipeline. Luckily for us, Select-String returns the file name of a match found, and the matched content so we just reference it in our Foreach-Object loop; could also use a calculated property instead.


    As for your quoting issues, you may have to double quote or escape the quotes within the PowerShell.exe call for it to run properly.

    Edit: swapped the double quotes for single quotes so you can wrap the entire expression in just PowerShell.exe -Command "expression here" without the need of escaping; this works if you're pattern to find doesn't contain single quotes.