This shows you how you can search in files for specific content with Windows PowerShell. This also “replaces” the Windows command-line utility “findstr”. In the Unix/Linux world, you mostly use the command grep for doing the same. So you can think of Select-String as PowerShell version of Grep. The Select-String cmdlet searches for text and text patterns in input strings and files. You can use Select-String similar to grep in UNIX or findstr in Windows.
grep syntax
grep (options) files.txt
grep example
grep "text I search" *.log
In Windows PowerShell we can use the Select-String to search strings in files
Select-String -Path C:\temp\*.log -Pattern "Contoso"
If you need some more options, for example, you need also check subfolders (-Recurse) or you need additional filter for files you wanna check, you can use the Get-Childitem first.
Get-ChildItem C:\temp -Filter *.log -Recurse | Select-String "Contoso"
If you have to copy all the files with a specific content, you can simply add a Copy-Item cmdlet.
Get-ChildItem C:\temp -Filter *.log -Recurse | Select-String "Contoso" | Copy-Item -Destination C:\temp2
More Information about Select-String on Microsoft Docs. Select-String can also be very useful to count your lines of code in different files using PowerShell.
PS C:\> Get-Help Select-String
NAME
Select-String
SYNOPSIS
Finds text in strings and files.
SYNTAX
Select-String [-Path] <string[]> [-Pattern] <string[]> [-AllMatches] [-CaseSensitive] [-Context <Int32[]>] [-Encoding <string>] [-Exclude <string[]>] [-Include <string[]>] [-List] [-NotMatch] [-Quiet] [-SimpleMatch] [<CommonParameters>]
Select-String -InputObject <psobject> [-Pattern] <string[]> [-AllMatches] [-CaseSensitive] [-Context <Int32[]>] [-Encoding <string>] [-Exclude <string[]>] [-Include <string[]>] [-List] [-NotMatch] [-Quiet] [-SimpleMatch] [<CommonParameters>]
DESCRIPTION
The Select-String cmdlet searches for text and text patterns in input strings and files. You can use it like Grep in UNIX and Findstr in Windows with Select-String in PowerShell.
Select-String is based on lines of text. By default, Select-String finds the first match in each line and, for each match, it displays the file name, line number, and all text in the line containing the match.
However, you can direct it to detect multiple matches per line, display text before and after the match, or display only a Boolean value (true or false) that indicates whether a match is found.
Select-String uses regular expression matching, but it can also perform a simple match that searches the input for the text that you specify.
Select-String can display all of the text matches or stop after the first match in each input file. It can also display all text that does not match the specified pattern.
You can also specify that Select-String should expect a particular character encoding, such as when you are searching files of Unicode text.
RELATED LINKS
Online version: http://go.microsoft.com/fwlink/?LinkID=113388
about_Comparison_Operators
about_Regular_ExpressionsREMARKS
To see the examples, type: “get-help Select-String -examples”.
For more information, type: “get-help Select-String -detailed”.
For technical information, type: “get-help Select-String -full”.PS C:\>
I hope this gives you an idea of how you can use a grep and findstr replacement in PowerShell using Select-String. Also, have a look at my blog post about how to install PowerShell 6 and PowerShell 7. If you have questions, let me know in the comments.
Tags: Copy-Item, findstr, Findstr in Powershell, Get-ChildItem, grep, grep in Powershell, Microsoft, PowerShell, Powershell findstr, Powershell grep, Search, search content in a file, Search for String, Select-String, String, Windows, Windows findstr, Windows Powershell Last modified: July 7, 2021
love it :)
Nice. Thanks
Nice post, I put it all together and made a script to search through folders and provide counts of occurrences for each file with the specified search string.
http://itandtechstuff.com/?p=38
This has been very useful for most cases.
I have had an issue when pipe delimited HL7 medication files. For example MSH^&|12325151|MedicationName
Are there certain characters that cause issue. Is there a way to get useful information from a failed command, maybe that could be a separate article.
‘findstr’ will do the job for cases when grep-like functionality is demanded without special options
(e.g. | grep “xx” is in powershell | findstr “xx”)
Hmm… these all didn’t work…
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “SMS”
PS C:\WINDOWS\system32> Get-Service | Select-String “SMS”
PS C:\WINDOWS\system32> Get-Service | Select-String SMS
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “.*SMS.*”
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “.*SMS.*” | Select Name
PS C:\WINDOWS\system32>
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “.*SMS.*” | Select Name | Format-Table
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “.*SMS.*” | Select Name, DisplayName | Format-Table
PS C:\WINDOWS\system32> Get-Service | Select-String -Pattern “SMS.*” | Select Name, DisplayName | Format-Table
PS C:\WINDOWS\system32> Get-Service | Select-String “SMS.*” | Select Name, DisplayName | Format-Table
PS C:\WINDOWS\system32> Get-Service | Select-String “.*SMS.*” | Select Name, DisplayName | Format-Table
PS C:\WINDOWS\system32> Get-Service | Select-String “.*SMS.*”
This is what worked:
PS C:\WINDOWS\system32> Get-Service | findstr “SMS”
Running CcmExec SMS Agent Host
Stopped SmsRouter Microsoft Windows SMS Router Service.
Hi Zoli
Select-String is working with Strings, however, you are piping an object with Get-Service (which is one of the great characteristics of PowerShell. Working with objects you would do something like this: Get-Service | where {$_.Name -like “*SMS*”} or a little bit cleaner: Get-Service | Where-Object {$_.Name -like “*SMS*”} or if you want to have it shorter but less nice in scripts: Get-Service | Where Name -like “*SMS*”
Select-String is more if you, for example, search something in a .txt file.
Hi Thomas, indeed, grep and findstr are only ever dealing with strings, and PowerShell commands are all enabled to work with object on the PowerShell pipeline. So while your clarification here ( where name -like “*SMS*” ) makes perfect sense, I’m still a bit confused:
Get-Service | sls “Sec” # cannot work because sls does not have a string to work with, makes sense.
Get-Service | findstr “Sec” # This works, because a DOS command only sees strings.
Side-note: sls is non-case-sensitive (like all PowerShell commands), but even though findstr is a Microsoft command, it *is* case-sensitive (as with all unix commands like grep).
So, my thinking here is immediately “ok, I need to make Get-Service a string then!”, but that doesn’t work … I don’t get why this won’t work, can you explain that?
Get-Service | Out-String | sls “Sec” # Doesn’t work, I don’t know why?
(Get-Service).ToString() | sls “Sec” # Doesn’t work, I don’t know why?
In fact, this one is worse as doing (Get-Service).ToString() just returns “System.Object[]”.
Clarification on this would be appreciated.
Get-Service | Out-String -Stream | sls “Sec”
The Out-String cmdlet converts the objects that Windows PowerShell manages into an array of strings. By default, Out-String accumulates the strings and returns them as a single string, but you can use the stream parameter to direct Out-String to return one string at a time
please try the below
Get-Service | Out-String -Stream | sls “Sec”
This line did not work for me:
Get-ChildItem C:\temp -Filter *.log -Recurse | Select-String “Contoso” | Copy-Item -Destination C:\temp2
I think because Select-String does not return FileInfo objects, but a MatchInfo object. I changed it to:
Get-ChildItem C:\temp -Filter *.log -Recurse | Select-String “Contoso” | Get-Item | Copy-Item -Destination C:\temp2
After posting this, I noticed that Get-Item en Copy-Item both act on an item, so I tried again. I guess I made some other mistake before, because the original line works just fine (doh!).
No problem :) Thank you for clarifying :)