Extract only the Pattern from Select-String - powershell

It's my first time using powershell and I'm a bit lost. I looked at the other answers on stackoverflow but I could not solve my problem.
I have a directory containing several files. These files each have a lot of lines. In these files I have to find the string ".MLB".
So I managed to build the following command :
Get-ChildItem -Path 'D:\Test\' -Include '*.txt' -Recurse | Select-String -Pattern 'MLB'
this seems to work. The problem is that it returns the whole line where my search appears which is very difficult to read.
I know that there is -Context to choose the number of line to display, but is it possible to do that with characters instead ? for example to display only the 20 characters that precede the pattern.
I've seen a few solution thanks to select-object but I have a really hard time to understand how to use it properly.
Thanks in advance.
EDIT: I made some progress. I tried the following:
Select-String -Path 'D:\TEST\log1.txt' -Pattern 'mlb' -AllMatches | ForEach-Object { $_.Matches.Value }
This returns the following
mlb mlb MLB mlb MLB
The only thing I need now would be a way to display what precede before that. Exemple:
data01a.mlb
data.mlb
DATE FILE MLB
HR.mlb
`

Related

How to remove files from several locations with similar paths but not identical paths

I'm trying to come up with a way in order to quickly remove multiple files that are in similar child directories. I need to accomplish the removals quickly to several domain controllers so they don't replicate and replace the deleted files.
The file paths vary slightly but enough and I was hoping to use wildcards (*) to cut down the six possible path variations to only two.
something along these lines:
The {} actually exist since they are hash values
C:\Windows\SYSVOL\domain\Policies\{*}\User*\Script\Logon\abc*
C:\Windows\SYSVOL\sysvol\xxxx\Policies\{*}\User*\Script\Logon\abc*
Initially I was thinking along the lines of using a recursive select-string search and pipe it to remove-item but I was getting an access denial error when i was just hypothesizing the search without the pipe to remove-item.
gci -path C:\Windows\SYSVOL\ -rec | select-string -pattern "domain\Policies\{*}\User*\Script\Logon\abc*
and
gci -path C:\Windows\SYSVOL\ -rec | select-string -pattern "sysvol\xxxx\Policies\{*}\User*\Script\Logon\abc*" | remove-item $_
(the remove-item is basically pseudo code)
I tried delimiting the {'s and 's but that didn't work either.
Once I have this working in theory I would then need to use the invoke-command to try to get this removal process to work its way through the list of systems that need this operation.
I don't know if this is the right approach / best approach, or if it is even doable.
Any advise would be greatly appreciated.

Is there a way to grab data from this txt file in Powershell?

I am using Beyond Compare and I have gotten it to ouput if there are any differences into a txt file. However, I want to script this in powershell so that if there are no differences in files, the script will continue and do something else. However, I am not sure this is possible. I have looked through Select-String, but unsure if that will be able to do what I am looking for. Attached is what the txt file looks like when there are no differences as well as what it looks like when there are differences.
Is it possible to convert name, size, or modified in the txt file into a variable and then do a condition on whether it is null? Or is there is another way I can do what I am trying to achieve in Powershell? Thanks in advance.
If all you need to know is whether any differences were found, the following should do:
$noDiffs = '' -eq ((Get-Content -Raw report.txt) -split '\r?\n-+\r?\n')[1].Trim()
(Get-Content -Raw report.txt) -split '\r?\n-+\r?\n splits the entire input file by the the divider line (----...) following the table-header line, using a regex (regular expression).
[1] looks a the 2nd element of the resulting array, i.e., whatever comes after the divider line, trims any leading and trailing whitespace, and the result is tested for being the empty string.
With all respect to the question and the answer from #mklement0.
Using Beyond Compare in a PowerShell script is putting the cart before the horse.
There are a lot of cmdlets in PowerShell which would let you easily compare folders (and a lot more) without doing any text scraping.
As using Compare-Object togehter with Get-ChildItem for the given example:
Compare-Object (Get-ChildItem .\Test) (Get-ChildItem .\Test1) -Property Name, Length, LastWriteTime
If you want to do a recursive compare on the relative path, you can do:
Compare-Object (Get-ChildItem .\Test -Recurse -Name) (Get-ChildItem .\Test1 -Recurse -Name)
Note that the -Name parameter will only list relative path strings, if you also want to compare Length and LastWriteTime, You can do:
$TestFolder = 'C:\Test'
$Test1Folder = 'C:\Test1'
$TestFiles = Get-ChildItem $TestFolder -File -Recurse |
Select-Object *,#{N='RelativePath'; E={$_.FullName.SubString($TestFolder.Length)}}
$Test1Files = Get-ChildItem $Test1Folder -File -Recurse |
Select-Object *,#{N='RelativePath'; E={$_.FullName.SubString($Test1Folder.Length)}}
Compare-Object $TestFiles $Test1Files -Property RelativePath,Length,LastWriteTime

Get a line number on Powershell?

So I have been searching a lot and couldn't find anything that wouldn't return me nothing.
I have a code with a variable and I have a file with a lot of lines on it.
For example, I have the following file (things.txt):
Ketchup
Mustard
Pumpkin
Mustard
Ketchup
And what I want to take out is the line numbers of "Mustard". Here's the code I'm trying right now
$search="Mustard"
$linenumber=Get-Content things.txt | select-string $search -context 0,1
$linenumber.context
But it actually returns "". Everyone online was about using context but I only want to know the line number of every "Mustard" which are 2 and 4.
Thanks for your help!
Select-String returns the line number for you. You're just looking at the wrong property. Change your code to:
$search="Mustard"
$linenumber= Get-Content thing.txt | select-string $search
$linenumber.LineNumber
For people who are searching for one liner, code is self explanatory.
Get-Content .\myTextFile.txt | Select-String -Pattern "IamSearching" | Select-Object LineNumber
Edit(April 2022):
OR
(Select-String .\myTextFile.txt -Pattern "IamSearching").LineNumber
Try insert -Path after Get-Content

Select-String - find a string that spans multiple lines

I am trying to read lines in a file and search for a pattern that spans two lines. Looking at the file in notepad++ I see a LF char in the file.
Example log.txt:
I want to find this
value here: OK
My simple code does not work and returns nothing:
select-string -Path "log.txt" -Pattern "find this\n*value here: OK"
I have tried many combos of various things here including .+ and \r that I found posted on various threads. I can get the first line by using:
select-string -Path "log.txt" -Pattern "find this\n*"
Result of above is: I want to find this
Adding anything more to the line above results in nothing being returned. Any ideas how to do this using select-string? I was trying to avoid using get content due to the potential size of the files I am working with.
So I think I understand your question. If you have a file that has a line that you want to key off of then the next line is the line that you want to look at:
(Select-String -Path "Log.txt" -Pattern "find this" -Context 1).Context.PostContext
I wasn't sure if that carriage return was an artifact of your formatting or not. If it is not then this would work better:
(Select-String -Path "Log.txt" -Pattern "find this" -Context 2).Context.PostContext[1]
Here is a way to do it if you don't know how many lines will be between the two bits:
$file = Get-Content 'Log.txt' -Raw
$file -match '(?smi)I want to find this.*(value here: OK)'
$matches[1]
Since you might want a multi line regex solution you need to read in the text file as one string.
Using the test file:
Stfuf
Bagel
I want to find this
value here: OK
Things
I was able to get the result using a simple matching pattern that satisfies your example text.
(Get-Content -Raw c:\temp\test.txt | Select-String -Pattern "([\w ]+)\s*value here: OK").Matches.Groups[1].Value
regex101.com
Basically gets the text preceding invariant spaces, including newlines and the static text "value here: OK". Could be made better with positive look aheads but this seems to work fine.

Powershell String search

I am trying to search a keyword/pattern match in a file, where the lines will be starting with date.
Line will be like below
11/02/15 02:28:49%%PROGRAM$$SUCCESS$$End.
So i tried with below command,
Select-String -Path C:\Path\To\File.txt -Pattern $(Get-Date -format d) | Select-String -Pattern SUCCESS
So that i can get lines which contain SUCCESS with a starting of current date.
Its working on my test box and when i tried the same on a big file (~200 MB), its not giving any results. Tried below too,
Get-Content -Path C:\Path\To\File.txt | Select-String -Pattern $(Get-Date -format d) | Select-String -Pattern SUCCESS
Any help any help would be greatly appreciated!
Some things to consider here. As PetSerAl brings to light, Get-Date -Format d depends on the culture, so you need to be careful about relying on the output of that.
If the files you're searching are generated using Get-Date -Format d then it makes sense to do the search that way as long as the files will always be searched on a machine with the same culture they were generated with.
By the way on my machine it's 11/2/2015 not 11/02/15 and I am in the US.
Also, when you use Select-String -Pattern it's a regular expression, so you need to make sure that there are no special characters in the string. In the case of PetSerAl's date, the dots . would be interpreted as special characters. To avoid that use [RegEx]::Escape().
Select-String returns a match object (or objects), so piping it directly into another Select-String may not work. Consider making a single pattern out of it.
Just a guess here, but it kind of seems like the pattern you want is to match the current date string at the beginning of the line and then find SUCCESS anywhere after that in the line.
I think for that you could use a pattern like this: 11/02/15.+?SUCCESS
So code like this:
Get-Content -Path C:\Path\To\File.txt | Select-String -Pattern "$([RegEx]::Escape((Get-Date -Format d))).+?SUCCESS"
Would do the trick I think, again assuming culture issues don't mess you up.