PowerShell FINDSTR eqivalent?

[亡魂溺海] 提交于 2021-02-05 20:24:55

问题


What's the DOS FINDSTR equivalent for PowerShell? I need to search a bunch of log files for "ERROR".


回答1:


Here's the quick answer

Get-ChildItem -Recurse -Include *.log | select-string ERROR 

I found it here which has a great indepth answer!




回答2:


For example, find all instances of "#include" in the c files in this directory and all sub-directories.

gci -r -i *.c | select-string "#include"

gci is an alias for get-childitem




回答3:


Just to expand on Monroecheeseman's answer. gci is an alias for Get-ChildItem (which is the equivalent to dir or ls), the -r switch does a recursive search and -i means include.

Piping the result of that query to select-string has it read each file and look for lines matching a regular expression (the provided one in this case is ERROR, but it can be any .NET regular expression).

The result will be a collection of match objects, showing the line matching, the file, and and other related information.




回答4:


if ($entry.EntryType -eq "Error")

Being Object Oriented, you want to test the property in question with one of the standard comparison operators you can find here.

I have a PS script watching logs remotely for me right now - some simple modification should make it work for you.

edit: I suppose I should also add that is a cmdlet built for this already if you don't want to unroll the way I did. Check out:

man Get-EventLog
Get-EventLog -newest 5 -logname System -EntryType Error



回答5:


On a related note, here's a search that will list all the files containing a particular regex search or string. It could use some improvement so feel free to work on it. Also if someone wanted to encapsulate it in a function that would be welcome.

I'm new here so if this should go in it's own topic just let me know. I figured I'd put it her since this looks mostly related.

# Search in Files Script
# ---- Set these before you begin ---- 
$FolderToSearch="C:\" # UNC paths are ok, but remember you're mass reading file contents over the network
$Search="Looking For This" # accepts regex format
$IncludeSubfolders=$True #BUG: if this is set $False then $FileIncludeFilter must be "*" or you will always get 0 results
$AllMatches=$False
$FileIncludeFilter="*".split(",") # Restricting to specific file types is faster than excluding everything else
$FileExcludeFilter="*.exe,*.dll,*.wav,*.mp3,*.gif,*.jpg,*.png,*.ghs,*.rar,*.iso,*.zip,*.vmdk,*.dat,*.pst,*.gho".split(",")

# ---- Initialize ----
if ($AllMatches -eq $True) {$SelectParam=@{AllMatches=$True}}
else {$SelectParam=@{List=$True}}
if ($IncludeSubfolders -eq $True) {$RecurseParam=@{Recurse=$True}}
else {$RecurseParam=@{Recurse=$False}}

# ---- Build File List ---- 
#$Files=Get-Content -Path="$env:userprofile\Desktop\FileList.txt" # For searching a manual list of files
Write-Host "Building file list..." -NoNewline
$Files=Get-ChildItem -Include $FileIncludeFilter -Exclude $FileExcludeFilter -Path $FolderToSearch -ErrorAction silentlycontinue @RecurseParam|Where-Object{-not $_.psIsContainer} # @RecurseParam is basically -Recurse=[$True|$False]
#$Files=$Files|Out-GridView -PassThru -Title 'Select the Files to Search' # Manually choose files to search, requires powershell 3.0
Write-Host "Done"

# ---- Begin Search ---- 
Write-Host "Searching Files..."
$Files|
    Select-String $Search @SelectParam| #The @ instead of $ lets me pass the hastable as a list of parameters.  @SelectParam is either -List or -AllMatches
    Tee-Object -Variable Results|
    Select-Object Path
Write-Host "Search Complete"
#$Results|Group-Object path|ForEach-Object{$path=$_.name; $matches=$_.group|%{[string]::join("`t", $_.Matches)}; "$path`t$matches"} # Show results including the matches separated by tabs (useful if using regex search)

<# Other Stuff
    #-- Saving and restoring results
    $Results|Export-Csv "$env:appdata\SearchResults.txt" # $env:appdata can be replaced with any UNC path, this just seemed like a logical place to default to
    $Results=Import-Csv "$env:appdata\SearchResults.txt"

    #-- alternate search patterns
    $Search="(\d[-|]{0,}){15,19}" #Rough CC Match
#>



回答6:


This is not the best way to do this:

gci <the_directory_path> -filter *.csv | where { $_.OpenText().ReadToEnd().Contains("|") -eq $true }

This helped me find all csv files which had the | character in them.




回答7:


PowerShell has basically precluded the need for findstr.exe as the previous answers demonstrate. Any of these answers should work fine.

However, if you actually need to use findstr.exe (as was my case) here is a PowerShell wrapper for it:

Use the -Verbose option to output the findstr command line.


function Find-String
{
    [CmdletBinding(DefaultParameterSetName='Path')]
    param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]
        $Pattern,

        [Parameter(ParameterSetName='Path', Mandatory=$false, Position=1, ValueFromPipeline=$true)]
        [string[]]
        $Path,

        [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias('PSPath')]
        [string[]]
        $LiteralPath,

        [Parameter(Mandatory=$false)]
        [switch]
        $IgnoreCase,

        [Parameter(Mandatory=$false)]
        [switch]
        $UseLiteral,

        [Parameter(Mandatory=$false)]
        [switch]
        $Recurse,

        [Parameter(Mandatory=$false)]
        [switch]
        $Force,

        [Parameter(Mandatory=$false)]
        [switch]
        $AsCustomObject
    )

    begin
    {
        $value = $Pattern.Replace('\', '\\\\').Replace('"', '\"')

        $findStrArgs = @(
            '/N'
            '/O'
            @('/R', '/L')[[bool]$UseLiteral]
            "/c:$value"
        )

        if ($IgnoreCase)
        {
            $findStrArgs += '/I'
        }

        function GetCmdLine([array]$argList)
        {
            ($argList | foreach { @($_, "`"$_`"")[($_.Trim() -match '\s')] }) -join ' '
        }
    }

    process
    {
        $PSBoundParameters[$PSCmdlet.ParameterSetName] | foreach {
            try
            {
                $_ | Get-ChildItem -Recurse:$Recurse -Force:$Force -ErrorAction Stop | foreach {
                    try
                    {
                        $file = $_
                        $argList = $findStrArgs + $file.FullName

                        Write-Verbose "findstr.exe $(GetCmdLine $argList)"

                        findstr.exe $argList | foreach {
                            if (-not $AsCustomObject)
                            {
                                return "${file}:$_"
                            }

                            $split = $_.Split(':', 3)

                            [pscustomobject] @{
                                File = $file
                                Line = $split[0]
                                Column = $split[1]
                                Value = $split[2]
                            }
                        }
                    }
                    catch
                    {
                        Write-Error -ErrorRecord $_
                    }
                }
            }
            catch
            {
                Write-Error -ErrorRecord $_
            }
        }
    }
}



回答8:


FYI: If you update to Powershell version 7 you can use grep... I know egrep is in powershell on Azure CLI... But SS is there! An old article here: [https://devblogs.microsoft.com/powershell/select-string-and-grep/]



来源:https://stackoverflow.com/questions/14708/powershell-findstr-eqivalent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!