218

I'm looking for the PowerShell equivalent to grep --file=filename. If you don't know grep, filename is a text file where each line has a regular expression pattern you want to match.

Maybe I'm missing something obvious, but Select-String doesn't seem to have this option.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fordio
  • 3,410
  • 2
  • 14
  • 18

9 Answers9

240

The -Pattern parameter in Select-String supports an array of patterns. So the one you're looking for is:

Get-Content .\doc.txt | Select-String -Pattern (Get-Content .\regex.txt)

This searches through the textfile doc.txt by using every regex(one per line) in regex.txt

Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • 8
    Also, PowerShell tab completion will make commands properly capitalized, so it is not hard to input. – joon Jan 02 '14 at 03:36
  • 4
    @joon A couple of years late, but I'd add that Powershell is case insensitive so the capitalization of commands is not an issue. – dee-see Jan 05 '17 at 17:58
  • 1
    @Vache of course - I think my comment above is a reply to another comment, but it seems the comment is gone anymore. – joon Jan 06 '17 at 06:21
  • 2
    @dee-see A couple of years late, but I'd add that *Windows* is case insensitive so the capitalization of commands, paths,... is not an issue. :) – pixis Mar 03 '21 at 17:20
125
PS) new-alias grep findstr
PS) C:\WINDOWS> ls | grep -I -N exe

105:-a---        2006-11-02     13:34      49680 twunk_16.exe
106:-a---        2006-11-02     13:34      31232 twunk_32.exe
109:-a---        2006-09-18     23:43     256192 winhelp.exe
110:-a---        2006-11-02     10:45       9216 winhlp32.exe

PS) grep /?
Underverse
  • 1,271
  • 21
  • 32
dawciobiel
  • 1,511
  • 1
  • 10
  • 11
  • 29
    I never understood how this got so many votes. It's doesn't even answer the question.. – Frode F. Sep 07 '16 at 16:00
  • 29
    What I like about this answer is that `findstr` works the most like `grep` on Linux does. `Select-String` is great for working with objects, but sometimes you just want to match on strings. – Elijah W. Gagne Dec 27 '16 at 21:34
  • 11
    It is worth noting that `findstr` is not native to PowerShell, but Command Prompt. – anishpatel May 16 '17 at 21:34
  • 1
    This findstr command was already available to me, and it worked just like unix GREP. – Lennon Nov 21 '18 at 14:32
  • 6
    @FrodeF. that's because this question is the first thing comes up when we search for "powershell grep equivalent". :) – skaveesh Aug 27 '21 at 07:11
  • Worth mentioning that `-I` is "insensitive" and `-N` includes the line number, and that in Windows you'd normally use `/i` and `/n`. Also note that the `/r` option for **regex is on by default**. All parameters for `findstr` are currently described [here](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/findstr#parameters). As best as I can tell, you use [`find` (no `str`)](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/find) to avoid regular expressions. – ruffin Dec 01 '21 at 13:27
  • Select-String isn't very good at doing line-based context, which grep is great at. – Dan May 02 '22 at 20:17
49

I'm not familiar with grep but with Select-String you can do:

Get-ChildItem filename.txt | Select-String -Pattern <regexPattern>

You can also do that with Get-Content:

(Get-Content filename.txt) -match 'pattern'
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
12

I had the same issue trying to find text in files with powershell. I used the following - to stay as close to the Linux environment as possible.

Hopefully this helps somebody:

PowerShell:

PS) new-alias grep findstr
PS) ls -r *.txt | cat | grep "some random string"

Explanation:

ls       - lists all files
-r       - recursively (in all files and folders and subfolders)
*.txt    - only .txt files
|        - pipe the (ls) results to next command (cat)
cat      - show contents of files comming from (ls)
|        - pipe the (cat) results to next command (grep)
grep     - search contents from (cat) for "some random string" (alias to findstr)

Yes, this works as well:

PS) ls -r *.txt | cat | findstr "some random string"
  • That's pretty good, but I also want the name of the file where it was found – Ken Seehart Dec 29 '20 at 06:08
  • @KenSeehart to get folder/file information you need to pipe that info as well, `cat` loses that info converting everything to string. You could run this command to achieve what you need `ls -r *.txt | select-string -pattern "some text" | Format-Table LineNumber, Filename, Line`. Same but with aliases: `ls -r *.txt | sls -pattern "some text" | ft LineNumber, Filename, Line` – Serj Dec 14 '22 at 14:56
  • From here: https://learn.microsoft.com/en-us/windows/wsl/setup/environment: Mix Linux and Windows commands: In this example, the Linux command `ls -la` is used to list files in the directory, then the PowerShell command `findstr` is used to filter the results for words containing "git": `wsl ls -la | findstr "git"`. This could also be done mixing the Windows `dir` command with the Linux grep command: `dir | wsl grep git`. – Serj Dec 19 '22 at 04:30
10

So I found a pretty good answer at this link: https://www.thomasmaurer.ch/2011/03/powershell-search-for-string-or-grep-for-powershell/

But essentially it is:

Select-String -Path "C:\file\Path\*.txt" -Pattern "^Enter REGEX Here$"

This gives a directory file search (*or you can just specify a file) and a file-content search all in one line of PowerShell, very similar to grep. The output will be similar to:

doc.txt:31: Enter REGEX Here
HelloWorld.txt:13: Enter REGEX Here
cody.tv.weber
  • 536
  • 7
  • 15
  • 2
    He wants to load the pattern from a file. – Rag Feb 22 '18 at 06:10
  • If that is what he is asking, there are other answers that are similar to mine, so I feel like the question may not be worded super clear of desired answer. But after rereading it, I agree that he probably is wanting to pipe regex from a file into select string. – cody.tv.weber Nov 05 '20 at 14:12
3

I find out a possible method by "filter" and "alias" of PowerShell, when you want use grep in pipeline output(grep file should be similar):

first define a filter:

filter Filter-Object ([string]$pattern) {
    Out-String -InputObject $_ -Stream | Select-String -Pattern "$pattern"
}

then define the alias:


    New-Alias -Name grep -Value Filter-Object

final, put the former filter and alias in your profile:

$Home[My ]Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Restart your PS, so you can use it:

alias | grep 'grep'


References

  1. alias: Set-Alias here New-Alias here

  2. Filter (Special function) here

  3. Profiles (just like .bashrc for bash): here

  4. out-string (this is the key) here:
    in PowerShell Output is object-based here,so the key
    is to convert object to string and grep the string.

  5. Select-String here:
    Finds text in strings and files

not2qubit
  • 14,531
  • 8
  • 95
  • 135
Lincoln Yesire
  • 159
  • 1
  • 4
1

This question already has an answer, but I just want to add that in Windows there is Windows Subsystem for Linux WSL.

So for example if you want to check if you have service named Elasicsearch that is in status running you can do something like the snippet below in powershell

net start | grep Elasticsearch

Ivan Ruski
  • 1,123
  • 1
  • 13
  • 19
0

but select-String doesn't seem to have this option.

Correct. PowerShell is not a clone of *nix shells' toolset.

However it is not hard to build something like it yourself:

$regexes = Get-Content RegexFile.txt | 
           Foreach-Object { new-object System.Text.RegularExpressions.Regex $_ }

$fileList | Get-Content | Where-Object {
  foreach ($r in $regexes) {
    if ($r.IsMatch($_)) {
      $true
      break
    }
  }
  $false
}
Richard
  • 106,783
  • 21
  • 203
  • 265
0

Maybe?

[regex]$regex = (get-content <regex file> |
foreach {
          '(?:{0})' -f $_
        }) -join '|'

Get-Content <filespec> -ReadCount 10000 |
 foreach {
           if ($_ -match $regex)
             {
              $true
              break
             }
         }
mjolinor
  • 66,130
  • 7
  • 114
  • 135