Finding Strings in Files on Windows

qwencoder version

 
# Literal search (case-insensitive)
# .\Search-Files.ps1 -Path "D:\PATH-" -Literal -Pattern "aString to search"
 
# Regex search
#.\Search-Files.ps1 -Path "C:\PATH" -Pattern "user\s*(id|name)\s*=\s*\d+"
 
param(
    [string]$Path = "C:\",
    [string]$Pattern = "Bulk Scanning Process",
    [switch]$Literal
)
 
$param = @{ Pattern = $Pattern; ErrorAction = 'SilentlyContinue' }
if ($Literal) { $param['SimpleMatch'] = $true }
 
Get-ChildItem $Path -Recurse -File -ErrorAction SilentlyContinue |
    Where-Object { $_.Extension -in '.txt', '.rtf', '.doc', '.docx', '.pdf' } |
    ForEach-Object {
        $file = $_
        switch ($file.Extension.ToLower()) {
            { $_ -in '.txt', '.rtf', '.doc' } {
                Select-String @param -Path $file.FullName | ForEach-Object {
                    [pscustomobject]@{ File = $file.FullName; Match = $_.Line }
                }
            }
            '.docx' {
                $tmp = Join-Path $env:TEMP ([IO.Path]::GetRandomFileName())
                try {
                    Expand-Archive $file.FullName $tmp -ErrorAction SilentlyContinue
                    $xml = Join-Path $tmp 'word\document.xml'
                    if (Test-Path $xml) {
                        Select-String @param -Path $xml | ForEach-Object {
                            [pscustomobject]@{ File = $file.FullName; Match = $_.Line }
                        }
                    }
                } finally {
                    Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue
                }
            }
            '.pdf' {
                try {
                    $text = [IO.File]::ReadAllText($file.FullName)
                    Select-String @param -InputObject $text | ForEach-Object {
                        [pscustomobject]@{ File = $file.FullName; Match = $_.Line }
                    }
                } catch {}
            }
        }
    }

Copilot Version

 
# .\search.ps1 -Root "C:\" -Pattern "bulk scanning"
# .\search.ps1 -Root "C:\" -Pattern "Bulk Scanning Process" -Literal
 
param(
    [string]$Root = "C:\",
    [string]$Pattern = "",
    [switch]$Literal
)
 
if (-not $Pattern) { throw "Pattern required." }
 
$matchParams = @{ Pattern = $Pattern; CaseSensitive = $false }
if ($Literal) { $matchParams.Literal = $true }
 
function Search-Docx {
    param($File, $matchParams)
 
    $tmp = Join-Path $env:TEMP ([IO.Path]::GetRandomFileName())
    try {
        Expand-Archive -Path $File.FullName -DestinationPath $tmp -ErrorAction SilentlyContinue
        $xml = Join-Path $tmp "word\document.xml"
 
        if (Test-Path $xml) {
            Select-String -Path $xml @matchParams -ErrorAction SilentlyContinue |
                ForEach-Object {
                    [PSCustomObject]@{
                        File  = $File.FullName
                        Match = $_.Line
                    }
                }
        }
    } catch {}
    finally {
        Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue
    }
}
 
function Search-Pdf {
    param($File, $matchParams)
 
    try {
        $text = [IO.File]::ReadAllText($File.FullName)
        $text | Select-String @matchParams -ErrorAction SilentlyContinue |
            ForEach-Object {
                [PSCustomObject]@{
                    File  = $File.FullName
                    Match = $_.Line
                }
            }
    } catch {}
}
 
$targets = Get-ChildItem $Root -Recurse -File -ErrorAction SilentlyContinue |
    Where-Object { $_.Extension -in ".txt", ".rtf", ".doc", ".docx", ".pdf" }
 
foreach ($f in $targets) {
    switch ($f.Extension.ToLower()) {
 
        ".txt" { 
            Select-String -Path $f.FullName @matchParams -ErrorAction SilentlyContinue |
                ForEach-Object { [PSCustomObject]@{ File=$f.FullName; Match=$_.Line } }
        }
 
        ".rtf" { 
            Select-String -Path $f.FullName @matchParams -ErrorAction SilentlyContinue |
                ForEach-Object { [PSCustomObject]@{ File=$f.FullName; Match=$_.Line } }
        }
 
        ".doc" { 
            Select-String -Path $f.FullName @matchParams -ErrorAction SilentlyContinue |
                ForEach-Object { [PSCustomObject]@{ File=$f.FullName; Match=$_.Line } }
        }
 
        ".docx" {
            Search-Docx -File $f -matchParams $matchParams
        }
 
        ".pdf" {
            Search-Pdf -File $f -matchParams $matchParams
        }
    }
}