Powershell как найти строку в файле

PowerShell Grep equivalent cmdlet is Select-String which uses regular expressions to search string in files. Select-String cmdlet in Powershell works similar to grep in UNIX and findstr in PowerShell.

Select-String searches for text or text patterns in the input string or file. It displays the file name, line number, and text in the line containing the match.

PowerShell grep equivalent Select-String
PowerShell grep equivalent Select-String

In this article, we will discuss PowerShell grep equivalent Select-String to search string in the files recursively using the Get-ChildItem, search string in the text that matches the patterns.

Get-ChildItem in PowerShell gets one or more child items based on search criteria.

Using the Select-String cmdlet in PowerShell with Get-ChildItem to search for the string in the file recursively.

Get-ChildItem -Path D:PowerShell -Recurse | Select-String -Pattern 'PSIsContainer' 

In the above PowerShell script, Get-ChildItem uses the parameter -Recurse to get one or more child items for the path specified and pipe output to the Select-String command.

PowerShell Tip: How to search for files in PowerShell!

Select-String uses a Pattern parameter to specify a string to find string in the file.

On successful match of string in a file, Select-String returns the filename, line number, and a line containing the search text in it.

The output of the grep equivalent Select-String command to find string in file is:

PowerShell search string in the file
PowerShell search string in the file

PowerShell find string in file

Use Select-String in PowerShell to find a string in the file. It uses regular expression matching to search for patterns in the file.

 Select-String -Path D:PowerShell*.* -Pattern 'Get-'  

In the above PowerShell script, Select-String uses Pattern ‘Get-‘ to search string in the file specified by the Path parameter.

The output of the script to grep a text file is:

PS C:> Select-String -Path D:PowerShell*.* -Pattern 'Get-'   
                                    
D:PowerShellGetFileProperties-Assignment.txt:1:Get-ChildItem -File | Select name,CreationTime
D:PowerShellprint-spooler-service-Test.ps1:1:$PrintSpooler = Get-Service -Name Spooler
D:PowerShellprint-spooler-service.ps1:1:$PrintSpooler = Get-Service -Name Spooler

Select-String displays the output on the console. It finds the string in the file and prints its filename, line number, and line containing the text.

PowerShell Tip: How to find the file last modified date using PowerShell!

Search for String in File Using Get-Content

The Get-Content gets the content of the file specified by the path parameter. It reads the content of the file and returns the string object.

Use the Get-Content to search for a string in the file using the following command.

Get-Content -Path C:Windowsmy.ini
Get-Content -Path C:Windowsmy.ini | Select-String -Pattern "basedir*"     

In the above PowerShell script,

The Get-Content reads the content of the file my.ini specified by the Path parameter.

It pipes the content of the string object to the Select-String command. It uses the Pattern parameter to find the string in the string object.

The output of the above script to search string in string object is:

Get-Content search string in object
Get-Content search string in object

Search String in Hash variable

Using the Select-String in PowerShell, you can search string in the hash variable.

let’s consider an example where hash contains the below key-value data pair and is stored in the $mysqlInfo variable.

$mysqlInfo = @{
basedir='C:/Program Files/mysql'

datadir='C:/Program Files/mysql/data'

port='3306'

}

Use the Select-String to specify the pattern to find the string in the variable.

$mysqlInfo |Out-String -Stream | Select-String -Pattern 'datadir'

In the above PowerShell script, the $mysqlInfo variable input pipes to the Out-String -Stream. It formatted the string objects into multiple single-line string objects.

Select-String uses the Pattern parameter to specify the input string to search in variable and returns the output as follows:

$mysqlInfo |Out-String -Stream | Select-String -Pattern 'datadir'

datadir          C:/Program Files/mysql/data   

PowerShell Tip: PowerShell Select-String Ignore Case search and CaseSensitive Search!

Conclusion

I hope the above article using the Select-String to search string in file and variable is helpful to you.

Use Select-String to find the string in file or variable similar to the grep command in UNIX and findstr in windows.

You can find more topics about PowerShell Active Directory commands and PowerShell basics on the ShellGeek home page.

В мире Linux/Unix для поиска определенного текста или ошибок в лог файлах используется команда grep. Grep позволяет быстро и удобно найти/выбрать любых данные из результатов выполнения другой команды:

command | grep search

В PowerShell для поиска текста в файлах можно использовать командлет Select-String.

Например, следующая команда выведет все строки текстового файла, содержащие ключевую фразу ERROR:

Select-String -Path c:tmpmakeapp_sxtracesxs.txt -Pattern "ERROR"

select-string поиск строки в файле с помощью PowerShell

Команда вывела номера строк, в которых содержится искомый тескт и их содержимое.

Если вам нужно выполнить поиск вхождения строки по всем txt файлам в определенном каталоге, выполните команду:

Select-String -Path c:tmp*.txt -Pattern "ERROR"

Такую команду удоно исопльзовать, если нужно выполнить поиск по всем файлам в каталоге. Например, для поиска в транспортных логах/smtp Exchange.

С помощью опций Exclude/Include можно включить, исключить определенннные файлы для поиска. Следующий пример выполнит поиск по всем txt и log файлам, имя которых не содежит copy:
$path = "c:tmp*"
Select-String -Path $path -Pattern "ERROR" -Include "*.txt","*.log" -Exclude "*copy*"

Предудущий пример выполняет поиск текста только в указанном каталоге. Для рекурсивного поиска по файлам во вложенных каталогах используйте Get-ChildItem:

Get-ChildItem -Path 'c:tmp' -Recurse -include "*.mp3","*.avi" -ErrorAction SilentlyContinue | Select-String -SimpleMatch "ERROR","WARNING"

When you need to search through a string or log files in Linux we can use the grep command. For PowerShell, we can use the grep equivalent Select-String. We can get pretty much the same results with this powerful cmdlet.

Select-String uses just like grep regular expression to find text patterns in files and strings. It can search through multiple files and report the location including the line number of the string for each file. It’s also possible to find only the first occurrence of string or for example, return only the files that don’t match a string.

  1. Finding a String with PowerShell Select-String
  2. Select-String Parameters
    • Showing lines before and after with Context
    • Return True or False with Quiet
    • Return only the matched string with Raw
    • Search through multiple file types
    • List only the files with Select-String
    • Return lines without pattern
    • Find files that not Match pattern
  3. PowerShell Select-String Recursive
  4. PowerShell Select-String Multiple Patterns
  5. Wrapping Up

In this article, we are going to take a look at the PowerShell grep equivalent Select-String. We are going to take a look at different examples that you can use to find a string with PowerShell. Make sure you read through the end for a nice little bonus tip!

Finding a String with PowerShell Select-String

Before we dive into all the possibilities of the select-string cmdlet, let’s first take a look at a couple of common examples. To search for a particular string in log files we can use the following cmdlet in PowerShell:

# Search for the string error in the path
Select-String -Pattern "error" -Path "C:templog*.log"

# or in short:
Select-String "error" "C:templog*.log"

The grep equivalent would be:

grep "error" .log*.log

By default, the output of the select-string cmdlet will show the filename, line number, and the complete line where the string was found:

powershell grep equivalent

Powershell Grep Equivalent

The advantage of PowerShell is that we can easily format the output to a more readable format. If you for example are only interested in the filename, path, and line number then you could format the results into a table and select only the fields that you need:

Select-String -Pattern "error" -Path "C:templog*.log" | Select LineNumber, FileName, Path

# Result:
LineNumber Filename         Path
---------- --------         ----
         9 01032022-app.log C:templog1032022-app.log
        18 04032022-app.log C:templog4032022-app.log
         7 05032022-app.log C:templog5032022-app.log
         9 11022022-app.log C:templog11022022-app.log
         9 11032021-app.log C:templog11032021-app.log
         9 11102021-app.log C:templog11102021-app.log
        38 11102021-app.log C:templog11102021-app.log
         9 15032022-app.log C:templog15032022-app.log

Select-String Parameters

So we have taken a quick look at the basic usage of the cmdlet, now let’s dive a bit deeper into all the possibilities of the search-string cmdlet in PowerShell. The cmdlet comes with a couple of parameters that will help us with searching for strings and selecting the results:

Parameter Description
-Pattern The text or string to find. Accepts a regular expression
-Path Specify the file or path to files to search through. Accepts wildcards
-CaseSensitive Search-string is case sensitive
-Context Show lines before and/or after the pattern
-Quiet Only return true or false
-Raw Return only the matched string like grep
-List List only the first match in the files. Used to get a list of files with pattern
-SimpleMatch Treat the pattern as a simple string
-Include Specifies files to include in the search (“*.txt”,”*.log”)
-Exclude Specifies files to exclude from the search path
-NotMatch Return only the items that didn’t match the pattern
-AllMatches Return all matches of the result
Select-String Parameters

Showing lines before and after with Context

The Select-String cmdlet returns the line where it found the string that we searched for. But when searching through log files, for example, you probably also want to know what happened before or after the error.

This is where the -context parameter comes in. It allows you to specify the number of lines that need to be returned for and/or after the matched line. The first digit is the number of lines before, the second is the number of lines after. If you only supply a single digit then it will be used for both.

# Return 3 lines before
Select-String -Pattern "error" -Path "C:templogsub*.log" -Context 3,0

# Return 2 lines before and 2 lines after the error:
Select-String -Pattern "error" -Path "C:templogsub*.log" -Context 2

The line that matched the pattern is indicated with > and the string is highlighted:

powershell select-string

PowerShell Select-String cmdlet

Return True or False with Quiet

When using the PowerShell grep equivalent select-string inside a script you sometimes only need to know if the string exists or not. By default, the cmdlet will return a MatchInfo object. An object with the line number, path, string, etc.

To check if the log files contain an error or not we can do the following:

# Returns true or False
Select-String -Pattern "error" -Path "C:templogsub*.log" -Quiet

# Result:
True

Return only the matched string with Raw

If you are used to the Linux grep command then you may have noticed that the result of select-string is slightly different. The PowerShell equivalent returns an object, instead of only the string that the grep command does.

When you add the -raw parameter to your command then the cmdlet will only return the string that matched the pattern:

Select-String -Pattern "error" -Path "C:templogsub*.log" -Raw

# Result:
2022-03-01 10:59:21 [ERROR] - String failed to be a string

Search through multiple file types

The path parameter already accepts wildcards, allowing us to search through multiple files. But in this case, we can only search through one file type. When using the -include parameter we can specify multiple file types that we want to search through.

To use the parameter we still need to supply the path, otherwise, the cmdlet will search in the script root location.

# Search in the txt and log files
Select-String -Pattern "error" -Path "C:templogsub*" -Include "*.txt","*.log"

# Result
C:templogsubLT3452-process.log:4:2022-03-01 10:59:21 [ERROR] - String failed to be a string
C:templogsubLT4423-process.txt:3:2022-02-01 05:49:21 [ERROR] - Squirrel failed to find process

It’s also possible to exclude file extensions with the -exclude parameter.

List only the files with Select-String

When searching through multiple files with the select-string cmdlet, PowerShell will return all instances of the string that it has found. But sometimes you only want to know if a log file, for example, contains an error.

If we search through the log files for the pattern error we can see that the file 11102021-app.log is found two times:

Select-String -Pattern "error" -Path "C:templog*" | Select LineNumber, Filename

# Result:
LineNumber Filename
---------- --------
         9 01032022-app.log
        18 04032022-app.log
         7 05032022-app.log
         9 11022022-app.log
         9 11032021-app.log
         9 11102021-app.log
        38 11102021-app.log
         9 15032022-app.log

By using the parameter -List only the first instances are returned, resulting in a unique list of filenames that contain the matching pattern:

Select-String -Pattern "error" -Path "C:templog*" -List | Select LineNumber, Filename

List only files

Unique files with -list parameter

Return lines without pattern

All this time we have been searching for strings inside log files that contain the string “error”. But what if you want to get the opposite? All the lines that don’t contain the word “error”?

For this, we can use the -NotMatch parameter. This will return all the lines in the path that don’t match the pattern that we have supplied:

Select-String -Pattern "error" -Path "C:templog*" -NotMatch | Select LineNumber, Filename

Find files that not Match pattern

The Select-String cmdlet searches on line level through files. This means that we can’t simply use this cmdlet to return only the files that don’t contain a particular string.

To get all the files that don’t contain the string we will need to use the Get-ChildItem cmdlet, and use the Select-String cmdlet on each file.

By using the -quiet parameter we can return true or false, allowing us to only select (and return) the files that don’t contain the pattern:

Get-ChildItem -path "C:templog*" | Where-Object { !( $_ | Select-String -Pattern "error" -Quiet ) }

# Result:

    Directory: C:templog

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           15-3-2022    13:52                sub
-a---           15-3-2022    14:09           4120 04032022-app.log
-a---           15-3-2022    12:59           2860 11032022-app.log

PowerShell Select-String Recursive

The select-string cmdlet in PowerShell only searches in the given directory. It won’t go through the subfolders, even if you use wildcards. To search in all subfolders as well we will need to combine the cmdlet with Get-ChildItem.

So to search in all subfolders we first will get all the items with Get-Childitem using the parameter -Recurse to search recursive. And then pass each file to the Select-String cmdlet:

Get-ChildItem -path "C:templog*" -Recurse | Select-String -Pattern "error" | Select LineNumber, Filename, Path

PowerShell Select-String Recursive

PowerShell Select-String Recursive

PowerShell Select-String Multiple Patterns

When searching through log files of other text files you sometimes need to search for multiple patterns. Now you could simply run the Select-String cmdlet twice, but that isn’t really efficient.

Luckily we can supply multiple patterns to the Select-String cmdlet. You can simply create an array with strings or comma-separated the strings:

Select-String -Pattern "error","warning" -Path "C:templog*" -List | Select LineNumber, Filename, Pattern

Multiple Patterns

Multiple Patterns

As you can see I have added the property Pattern to the select statement. This way we can see which pattern has matches in the file and on which line.

Wrapping Up

The PowerShell grep equivalent Select-String is a great tool to find strings inside text files or other output streams. If you really like to use the command grep, then I have a small tip for you. You can create a new alias in PowerShell so that the select-string cmdlet is used when you type grep.

To create the alias type:

new-alias grep select-string

Now you can use grep just like in Linux:

grep powershell

Grep Alias

I hope you found this article useful, if you have any questions, just drop a comment below.

В Powershell есть командлет, похожий на grep в Linux, Select-String. С помощью него мы можем искать как файлы, так и вхождения строк и, по желанию, используя регулярные выражения.

Для поиска внутри файла можно выполнить следующий командлет:

Select-String -Path *.txt -Pattern "fix"

Где:

  • Path – путь до директории или документа. В моем случае будут искаться все файлы с расширением .txt, т.к. знак * говорит что мы не знаем что находится слева. Если путь не указан, то он используется по умолчанию, откуда запущен powershell.
  • Pattern – строка, которую мы ищем внутри файла. Этот ключ используется для регулярных выражений. Для использования простого поиска, без регулярки, нужно ставить -SimpleMatch

Powershell Grep поиск строки

Мы можем искать не только в файлах, но и в самих строках:

$str = "Hello World"
Select-String -InputObject $str -SimpleMatch "hello","idk"

Где:

  • InputObject – объект, в котором мы будем искать переменную
  • SimpleMatch – простое совпадение. В моем случае их два. Если “hello” или “idk” будет в строке, то команда вернет строку.

Если мы используем путь в какую-то папку, то мы можем включать и исключать какие-то свойства:

$path =  "C:Folder1New folder*"
Select-String -Path $path -SimpleMatch "fix" -Include "*.txt" -Exclude "text*" -CaseSensitive

Где:

  • $path – переменная с путем, которая включает все файлы в папке “New Folder”.
  • Include – включает все файлы. В моем случае с расширением .txt
  • Exclude – исключает все файлы, которые начинаются на text.
  • CaseSensitive – учет регистра. В powershell, по умолчанию, буква “а” и “А” одинаковые, а с этим ключом они будут разными.

Т.к. командлет ищет только в текущей папке, но мы можем использовать другой, который рассматривался тут, для более глубокого поиска файлов через Powershell:

Get-ChildItem -Path 'C:Folder1' -Recurse -Exclude "*.mp3" | Select-String -SimpleMatch "fix"

Где:

  • Recurse – рекурсивный поиск т.е. поиск по всем папкам включительно.
  • Exclude – исключаем файлы с расширением mp3

Если в папке много файлов, то конечно быстрее будет сначала отфильтровать файлы через powershell Get-ChildItem, а затем искать в них нужные строки через Select-String.

С помощью такой команды мы можем исключить файлы, к которым у нас нет доступа иначе может быть ошибка:

Get-ChildItem -Path 'C:Folder1' -Recurse -Exclude "*.mp3" -ErrorAction SilentlyContinue | 
  Select-String -SimpleMatch "fix" -NotMatch

Где:

  • NoMatch – говорит, что нам нужны только те строки, где нет “fix” или дословно “Не совпадает”
  • ErrorAction – со значением SilentlyContinue – говорит “не уведомлять об ошибках”.

Разницу с Nomatch можно увидеть на картинке:

Powershell Grep поиск файлов

Если файл или строка в другой кодировке, то мы можем указать дополнительный ключ в виде -Encoding. Он может принимать следующие значения:

  • ASCII
  • BigEndianUnicode
  • OEM
  • Unicode
  • UTF7
  • UTF8
  • UTF8BOM
  • UTF8NoBOM
  • UTF32

Теги:

#powershell

Cover image for How to "grep" in PowerShell

PowerShell is awesome if you haven’t used it but it’s absolutely foreign if you’re used to Unix-like Bash-like shells. For instance, there’s no grep, and ls -al won’t work (but ls will and it’ll display all files with details!).

If you switch from Linux to Windows, you might be tempted to either install Cygwin or all of your GNU utilities. Or you might go the Linux subsystem route (which is a totally fair way to go) but if you want to go the PowerShell route, here’s a neat little tip!

What’s grep?

Grep is basically a utility that lets you filter some data using various patterns. There’s a LOT more to it but my own common usage of it is:

$ cat .bash_history | grep ssh
ssh root@0.0.0.0
ssh deploy@0.0.0.0
ssh ubuntu@0.0.0.0

Enter fullscreen mode

Exit fullscreen mode

This will filter out the output of cat and return only commands that include ssh. I use this to remind myself of IPs of servers I’ve recently used. Or I might do this:

$ cat package.json | grep webpack
    "start:dev": "webpack --config webpack/dev.config.js",
    "webpack": "3.8.1",
    "webpack-dev-server": "^2.9.4",
    "webpack-merge": "^4.1.1",

Enter fullscreen mode

Exit fullscreen mode

to get all of my webpack plugins, scripts, and figure out the latest version of webpack. It’s a handy utility, and I use it all the time. To filter lists of files in a folder and pipe them to another command or whatever else.

Grep is POWERFUL and it’s super featureful but I won’t get into that in this article.

So what does PowerShell have that’s the equivalent?

Introducing Select-String

One thing that’s immediately apparent about PowerShell is that its commands have better naming conventions. In fact, PS script is more like a programming language than Bash.

PowerShell piping is like Bash piping though it has some differences that I won’t go into right now.

cat package.json | Select-String -Pattern webpack
ls ./src/components/ | Select-String -Pattern View

Enter fullscreen mode

Exit fullscreen mode

Select-String supports regular expressions so you can also write more complicated stuff like:

C:> cat post.md | Select-String -Pattern "^w*:"

title: How to "grep" in PowerShell
published: false
description:
tags:

Enter fullscreen mode

Exit fullscreen mode

This will extract the front-matter from this post (at the time of writing this section).

How about searching through multiple files?

Absolutely! Grep has a pretty easy syntax for it: grep $PATTERN glob/pattern/**. An -r flag will recursively search through a path.

You might use it to identify where you’re using @select in your Angular application. @select is a decorator provided by the angular-redux store.

$ grep -r "@select" *.ts
comments-list.component.ts:  @select(['comments']) comments: Observable<IComment[]>;
comments-list.component.ts:  @select(authorsSelector) authors: Observable<any>;
comments-list.component.ts:  @select(['topComment']) topComment: Observable<IComment>;

Enter fullscreen mode

Exit fullscreen mode

So what about PowerShell? In PowerShell, you have to specify an argument but the explicitness actually makes a lot of sense:

C:> Select-String -Path *.ts -Pattern "@select"

comments-list.component.ts:51:  @select(['comments']) comments: Observable<IComment[]>;
comments-list.component.ts:53:  @select(authorsSelector) authors: Observable<any>;
comments-list.component.ts:55:  @select(['topComment']) topComment: Observable<IComment>;

Enter fullscreen mode

Exit fullscreen mode

Cool, what about recursion? Err…well, to have true recursion working and scan “n” levels deep, you’ll need to string a few commands together so we’ll skip that for now.

Happy PowerShelling!

Advanced Examples

Before I leave, I’d like to impart some fun advanced commands. Like I said, PowerShell piping isn’t like Linux piping. One of the big differences is that PowerShell utilizes “objects”.

So here’s a great example:

C:> Select-String -Path *.ts -Pattern "@select" | Select Filename, LineNumber, Line, Path | Format-Table

Enter fullscreen mode

Exit fullscreen mode

What this will do is: find files and matches to our pattern in all of TypeScript files in our current directory, select only the information we want to see, and transform it into a nice looking table like so (edited to fit site width):

Filename                    LineNumber   Line               Path
--------                    ----------   ----               ----
comments-list.component.ts  51           @select(['comme... C:comments-list...
comments-list.component.ts  53           @select(authors... C:comments-list...
comments-list.component.ts  55           @select(['topCo... C:comments-list...

Enter fullscreen mode

Exit fullscreen mode

You can then save it into a file via Out-File <filename> like so:

C:> Select-String -Path *.ts -Pattern "@select" | Select Filename, LineNumber, Line, Path | Format-Table | Out-File selectors.txt

Enter fullscreen mode

Exit fullscreen mode

Or output to a CSV:

C:> Select-String -Path *.ts -Pattern "@select" | Select Filename, LineNumber, Line, Path | Format-Table | Export-Csv -path selectors.csv -NoTypeInformation

Enter fullscreen mode

Exit fullscreen mode

What I love about PowerShell is that this stuff is built-in and it has sensible names. When I read bash scripts, it can be confusing. I mean, what does awk do? What about sed? Can you infer their jobs based on their names? Or what their flags mean?

Добавить комментарий