<# .SYNOPSIS Searches for files with specified extensions in a directory and optionally searches file contents for a regex pattern. .DESCRIPTION The Invoke-FileSearch function searches for files in a specified directory, either recursively or non-recursively, matching either a predefined set of extensions (e.g., .ps1, .bat) or user-specified extensions. It can also search file contents for a provided regex pattern, streaming results to stdout as they are found. The function supports local and network paths and handles errors gracefully. .PARAMETER Path The root directory path to start the search. Supports local paths and UNC paths (e.g., \\server\share). This parameter is mandatory. .PARAMETER Extensions An array of file extensions to search for (e.g., 'ps1', 'bat'). Extensions can be specified with or without the leading '*.'. Used with the 'Specific' parameter set. If not provided, the function defaults to the 'All' parameter set. .PARAMETER All Specifies to search for a predefined set of file extensions (.ps1, .cmd, .vbs, .vba, .conf, .jobx, .bat, .ini, .bak). Used with the 'All' parameter set, which is the default. .PARAMETER RegexPattern A regular expression pattern to search for within file contents. Requires the -IncludeContent switch. .PARAMETER Recurse If specified, searches subdirectories recursively. Defaults to $true. .PARAMETER IncludeContent If specified, enables searching file contents for the provided -RegexPattern. Without this switch, only file paths are returned. .EXAMPLE Invoke-FileSearch -Path "C:\Scripts" -Recurse Searches recursively for files with default extensions (.ps1, .cmd, etc.) in C:\Scripts and outputs their full paths to stdout. .EXAMPLE Invoke-FileSearch -Path "\\server\share\Scripts" -Extensions "ps1", "bat" -Recurse Searches recursively for .ps1 and .bat files in the specified network share and outputs their full paths to stdout. .EXAMPLE Invoke-FileSearch -Path "C:\Scripts" -All -RegexPattern "function\s+\w+" -IncludeContent Searches recursively for files with default extensions, checks their contents for PowerShell function declarations, and outputs custom objects with file paths and matches to stdout. .EXAMPLE Invoke-FileSearch -Path "C:\Scripts" -Extensions "ini" -Recurse:$false Searches non-recursively for .ini files in C:\Scripts and outputs their full paths to stdout. .INPUTS System.String Accepts a string input for the -Path parameter via pipeline. .OUTPUTS System.String Outputs full file paths as strings when -RegexPattern and -IncludeContent are not used. PSCustomObject Outputs custom objects with FilePath (string) and Matches (MatchInfo) properties when -RegexPattern and -IncludeContent are used. .NOTES - The function streams output to stdout, making it memory-efficient for large directories. - Errors accessing directories or reading files are handled gracefully, with warnings for file-specific issues. - Network shares are supported, but authentication may require additional configuration (e.g., credentials via PSDrive). - Performance may be slower when using -IncludeContent due to file content reading, especially on network shares. .LINK Get-ChildItem Select-String #> function Invoke-FileSearch { [CmdletBinding(DefaultParameterSetName = 'All')] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [string]$Path, [Parameter(ParameterSetName = 'Specific')] [string[]]$Extensions, [Parameter(ParameterSetName = 'All')] [switch]$All, [Parameter()] [string]$RegexPattern, [Parameter()] [switch]$Recurse = $true, [Parameter()] [switch]$IncludeContent ) begin { $defaultExtensions = @('*.ps1', '*.cmd', '*.vbs', '*.vba', '*.conf', '*.jobx', '*.bat', '*.ini', '*.bak') $searchExtensions = if ($PSCmdlet.ParameterSetName -eq 'All') { $defaultExtensions } else { $Extensions | ForEach-Object { if ($_ -notmatch '^\*\.') { "*.$_" } else { $_ } } } } process { try { Get-ChildItem -Path $Path -Recurse:$Recurse -Include $searchExtensions -File -ErrorAction SilentlyContinue | ForEach-Object { $filePath = $_.FullName if ($RegexPattern -and $IncludeContent) { try { $content = Get-Content -Path $filePath -Raw -ErrorAction SilentlyContinue if ($content -match $RegexPattern) { $result = [PSCustomObject]@{ FilePath = $filePath Matches = ($content | Select-String -Pattern $RegexPattern).Matches } Write-Output $result } } catch { Write-Warning "Error reading file: $filePath - $_" } } else { Write-Output $filePath } } } catch { Write-Error "Error searching files: $_" } } }