In powershell is that a way to put multiple search pattern ? Example below command, I want to search those string that has ASA or TMP. But it doesn't work. The search should match as a single word example: ASA is true but TIASAP is false
Get-ChildItem E:\Test\Workflow -Exclude *.bak -Recurse | Select-String -pattern "ASA" -or "TMP" -SimpleMatch | Where-Object LineNumber -le 50 | group path | select name
If you omit the -SimpleMatch switch, the Select-String cmdlet uses regex so you can just search for ASA|TMP:
Get-ChildItem E:\Test\Workflow -Exclude *.bak -Recurse | Select-String -pattern "ASA|TMP" | Where-Object LineNumber -le 50 | group path | select name
Just pass a list of strings you want to match to the -Pattern parameter.
For example, to search all ps1 files for the words function or check do:
Get-ChildItem *.ps1 | Select-String -Pattern function,check
This would make your example:
Get-ChildItem E:\Test\Workflow -Exclude *.bak -Recurse | Select-String -pattern ASA,TMP -SimpleMatch
Related
I have a textbox that takes an input and searches a drive.
Drive for example is C:/users/me
let's say I have multiple files and subdirectories in there and I would like to search if the following strings exist in the file: "ssn" and "DOB"
Once user inputs the two strings. I split the string but space, so I can loop through the array. But here is my current code, but I'm stuck on how to proceed.
gci "C:\Users\me" -Recurse | where { ($_ | Select-String -pattern ('SSN') -SimpleMatch) -or ($_ | Select-String -pattern ('DOB') -SimpleMatch ) } | ft CreationTime, Name -Wrap -GroupBy Directory | Out-String
this above code works if i pasted it manually into powershell but I'm trying to recreate this in a script but having confusion and how to do so.
this code below is not getting all the files needed.
foreach ($x in $StringArrayInputs) {
if($x -eq $lastItem){
$whereClause = ($_ | Select-String -Pattern $x)
}else{
$whereClause = ($_ | Select-String -Pattern $x) + '-or'
}
$files= gci $dv -Recurse | Where { $_ | Select-String -Pattern $x -SimpleMatch} | ft CreationTime, Name -Wrap -GroupBy Directory | Out-String
}
Select-String's -Pattern parameter accepts an array of strings (any one of which triggers a match), so piping directly to a single Select-String call should do:
$files= Get-ChildItem -File -Recurse $dv |
Select-String -List -SimpleMatch -Pattern $StringArrayInputs } |
Get-Item |
Format-Table CreationTime, Name -Wrap -GroupBy Directory |
Out-String
Note:
Using -File with Get-ChildItem makes it return only files, not also directories.
Using -List with Select-String is an optimization that ensures that at most one match per file is looked for and reported.
Passing Select-String's output to Get-Item automatically binds the .Path property of the former's output to the -Path parameter of the latter.
Strictly speaking, binding to -Path subjects the argument to interpretation as a wildcard expression, which, however, is generally not a concern - except if the path contains [ characters.
If that is a possibility, insert a pipeline segment with Select-Object #{ Name='LiteralPath'; Expression='Path' } before Get-Item, which ensures binding to -LiteralPath instead.
I just followed your examples and combined both with a regex. I escaped the regex to avoid accidential usage of expressions (like a dot for any char).
It is working with my testfiles but may differ with your files. You may need to add " -Encoding UTF8" with your appropriate encoding so you may get regional specific chars as well.
$String = Read-Host "Enter multiple strings seperated by space to search for"
$escapedRegex = ([Regex]::Escape($String)) -replace "\\ ","|"
Get-ChildItem -Recurse -Attributes !Directory | Where-Object {
$_ | Get-Content | Select-String -Pattern $escapedRegex
} | Format-Table CreationTime, Name -Wrap -GroupBy Directory | Out-String
The following snippet extracts only the matching lines, I also want the path and line number:
Get-ChildItem $thePath\ -Include "*.txt" -Recurse | Get-Content | Select-String -Pattern 'THE_PATTEN' | Set-Content "output.txt"
I tried with this method and still it only extracts the matching lines:
Get-ChildItem $thePath\ -Include "*.txt" -Recurse | Get-Content | Select-String -Pattern 'THE_PATTEN' | Select-Object -ExpandProperty Line | Set-Content "output.txt"
How can I extract the path:filename:line number: matching line?
You don't need get-content. The path is passed over the pipe. (. is for -path, and *.txt is for -filter for speed)
get-childitem -recurse . *.txt | select-string hi
foo2\file3.txt:1:hi
file1.txt:1:hi
file2.txt:1:hi
First note that Get-ChildItem -Filter is way more efficient than Get-ChildItem -Include (see help get-childitem). Next is that Select-String accepts files. No need to get the content first. Now just Select the properties you need and export your file. (Note that the variable $match and $matches are system variables so you might not want to use them.)
$Patterns = Get-ChildItem $thePath -Filter "*.txt" -Recurse| Select-String -Pattern 'THE_PATTEN' | select Path,Filename,LineNumber,Line
# Export to csv (usable in excel)
$Patterns | Export-Csv output.csv -NoTypeInformation # -Delimiter ";" # the delimiter is optinal and depending of your region
# Exporting txt
foreach ($Pattern in $Patterns){
('{0} : {1} : {2}' -f ($Pattern.Path),($Pattern.LineNumber),($Pattern.Line)) | Add-Content "output.txt"
}
Yea, you can get line number and file name from the output of Select-String:
ls *.txt | % { Select-String -Path $_ -Pattern "THE_PATTERN" | select-object LineNumber, Line, Path }
You'll notice this approach is also a touch faster.
Good luck!
I've got the following pipeline:
dir -recurse *.* | sls -pattern "matching_pattern" | select -unique path
Which gives me an output like this:
Path
----
D:\code\a.txt
D:\code\b.txt
I want it to call the command gvim a.txt b.txt.
How do I do this?
Use Where-Object instead of Select-String for filtering the files, expand the FullName (or Name) property, so you get an array of paths or filenames, and splat it when calling gvim:
$files = Get-ChildItem -Recurse *.* |
Where-Object { (Get-Content $_.FullName) -match "matching_pattern" } |
Select-Object -Unique -Expand FullName
& gvim #files
Replace FullName with Name in the Select-Object statement to get just the filenames without path.
If you want to stick with Select-String the approach would be similar:
$files = Get-ChildItem -Recurse *.* |
Select-String -Pattern "matching_pattern" |
Select-Object -Unique -Expand Path
& gvim #files
Replace Path with Filename in the Select-Object statement to get just the filenames without path.
You could access the two results by index:
$result = dir -recurse *.* | sls -pattern "matching_pattern" | select -unique path
gvim $result[0].FullName $result[1].FullName
I wrote below command to search all files within Workflow folders and look for only those files that matched pattern 'TextBox.TextBox'. It worked fine.
Now I want to change the command so it only search pattern from line 1 till line 50, instead to search whole file. How can I do that ?
Get-ChildItem E:\Test\Workflow -Recurse | Select-String -pattern "TextBox.TextBox" -SimpleMatch | group path
| select name | measure
You could use Get-Content and Select-Object -First:
Get-ChildItem E:\Test\Workflow -Recurse |ForEach-Object {
Get-Content -Path $_.FullName |Select-Object -First 50
} |Select-String -Pattern "TextBox.TextBox" -SimpleMatch
You can use the Where-Object cmdlet to filter all matches with LineNumber less equal 50:
Get-ChildItem E:\Test\Workflow -Recurse | Select-String -pattern "TextBox.TextBox" -SimpleMatch | Where-Object LineNumber -le 50 group path
I am curious how to produce a distinct file list based on this example.
** This example produces a list of all .ps1 and .psm1 files that contain the text "folders", but without the text ".invoke" on the same line.
$text='folders'
dir C:\Workspace\mydirectorytosearch1\ -recurse -filter '*.ps*1' | Get-ChildItem | select-string -pattern $text | where {$_ -NotLike '*.invoke(*'}
dir C:\Workspace\mydirectorytosearch2\ -recurse -filter '*.ps*1' | Get-ChildItem | select-string -pattern $text | where {$_ -NotLike '*.invoke(*'}
This is cool and works well but I get duplicate file output (same file but different line numbers).
How can I keep my file output distinct?
The current undesirable output:
C:\Workspace\mydirectorytosearch1\anonymize-psake.ps1:4:. "$($folders.example.test)\anonymize\Example.vars.ps1"
C:\Workspace\mydirectorytosearch1\anonymize-psake.ps1:5:. "$($folders.missles)\extract\build-utilities.ps1"
The desired output:
C:\Workspace\mydirectorytosearch1\anonymize-psake.ps1
Help me tweak my script??
You can eliminate duplicates wit Select-String and the Unique parameter:
$text='folders'
Get-ChildItem C:\Workspace\mydirectorytosearch1\,C:\Workspace\mydirectorytosearch2\ -Recurse -Filter '*.ps*1' |
Select-String -Pattern $text | Where-Object {$_ -NotLike '*.invoke(*'} |
Select-Object Path -Unique