diff options
| -rw-r--r-- | Invoke-FileSearch.ps1 | 132 | 
1 files changed, 132 insertions, 0 deletions
| diff --git a/Invoke-FileSearch.ps1 b/Invoke-FileSearch.ps1 new file mode 100644 index 0000000..4124548 --- /dev/null +++ b/Invoke-FileSearch.ps1 @@ -0,0 +1,132 @@ +<# +.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: $_" +        } +    } +} |