Check text file content in PowerShell - powershell

The PowerShell command
Get-ADFSRelyingPartyTrust | select Name | out-file C:\listOfNames.txt
generates a file as follows:
Name
----
AustriaRP
BahamasRP
BrazilRP
CanadaRP
[...]
Now, how can I check if BrazilRP has been extracted and C:\listOfNames.txt contains it?

The Get-Content and then Select-String should help. If the string is in the file it will get returned. If not then the command will returned empty value.
Get-Content C:\listOfNames.txt | Select-String "BrazilRP"
If the "BrazilRP" occurs more than once all the occurrences will returned so you know if you got any duplicates. Same holds if the string is a part of a longer expression. For example if you search for "zil" then "BrazilRP" will be returned as well.
Also you can pipe the results out to another file:
Get-Content C:\listOfNames.txt | Select-String "BrazilRP" | Out-File C:\myResults.txt

I found a solution (but thanks to PiotrWolkowski to suggest me the Get-Content function):
$file = Get-Content "C:\listOfNames.txt"
$containsWord = $file | %{$_ -match "BrazilRP"}
if ($containsWord -contains $true) {
Write-Host "There is!"
} else {
Write-Host "There ins't!"
}

If you want to easily see if a file contains your text try this
The [bool] type returns the data as either true or false instead of returning the actual data your searching for
if ([bool]((Get-Content -Path "C:\listOfNames.txt") -like '*BrazilRP*')) {
write-host "found it"
}
else {
write-host "didnt find it"
}

Related

Powershell - replace line in .txt if condition is met

i'm quite new to scripting (few weeks) and would be happy about your help.
I've a log-file (.txt) which needs to be changed.
The content is always the same:
random text
random text
successfull
error
random text
random text
random text
error
...
I would like to remove the line containing the word "error", but only if the line above contains the word "successfull".
So far I managed to get all the matching strings out of the File and am able to replace them, but I lose the rest of the text in the process:
get-content "D:\test.txt" | select-string -pattern "error" -context 1,0 | Where-Object {"$_" -match "successfull" } | %{$_ -replace "error.*"} | Out-File "D:\result.txt"
I would really appreciate your help here.
You can use some conditional logic (if statements) to achieve the goal:
$successful = $false
Get-Content d:\test.txt | Foreach-Object {
if ($_ -match "successfull") {
$successful = $true
$_
}
elseif ($_ -match "error" -and $successful) {
$successful = $false
}
else {
$_
$successful = $false
}
}
Since we are piping the Get-Content result into Foreach-Object, $_ becomes the current line being processed (each line is processed one by one). If a line contains successfull, then we mark $successful as $true and still output that line ($_). If the line contains error, then we will only output it if $successful is $false. Anytime we reach a line that does not contain succcesfull, we mark $successful as $false.
No deletion is actually occurring as it is merely not displaying error lines when the conditions are met.

Changing a value in a CSV returns a 0 length file

I have a script that changes a value in a column to '1'. However, the script writes a zero length file. I did some write-host to make sure that data should actually be piped to Export-Csv but still its only outputting a zero length file.
Import-Csv D:\sysutil\scratch\rap7logs\csv\noxsv.05-01-20.csv |
Foreach-Object {
$_.'result' = '1'
#write-host $_.'timestamp'
#write-host $_.'destination_user'
#write-host $_.'result'
} | Export-Csv D:\sysutil\scratch\rap7logs\csv\noxsv.05-01-20a.csv -NoTypeInformation```
Export-Csv will operate on what's piped to it by Foreach-Object, however your Foreach-Object is performing an action with no output, so there's nothing for Export-Csv to write.
You need to have Foreach-Object output the same input object like this...
Foreach-Object {
$_.'result' = '1'
$_
}
...or like this...
Foreach-Object {
$_.'result' = '1'
return $_
}
...in order for the modified object to make it to Export-Csv.

Powershell issue with do while loop

I've got a simple bit of code that looks for a string in a series of log files.
If it finds the string, it should exit the loop (nested inside another loop as part of a function) with $buildlogsuccess = 'True'
If it can't find the string, it should exit and return $buildlogsuccess = 'False'
The select-string statement itself works, however it looks like there's something wrong with the below code:
$logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
$count = ($logArr).count
Foreach ($log in $logArr) {
Do {
$count -= 1
$buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
If (($buildlogsuccess)) {break}
} while ($count -gt '0')
}
When one of the logs has the string, the loop finishes and should return $buildlogsuccess as 'True'.
If I check $log it shows the file that I know has the string (in this instance C:\build\Logs\Installer1.log).
Strangely, at this point $count shows as having a value of -1?
If I take the string out of that file and run again it also exits and returns the correct variable value (and shows the $log variable as the last file in $logArr as expected), but this time $count shows as -24.
My code is also returning $buildlogsuccess as 'False' when the string is present in one of the log files.
Re-tested [bool](select-string -path $log -simplematch $buildstring) by manually populating $log (with a file that has that string) and $buildstring and get 'True' as expected when using
[bool](select-string -path $log -simplematch $buildstring)
Note: Variables it uses:
$buildstring = "Package
'F:\xxx\Bootstrap\apackage\Installsomething.xml' processed
successfully"
Any help identifying where I've gone wrong would be appreciated.
Your code can be greatly simplified:
$buildlogsuccess = Select-String -SimpleMatch -Quiet $buildstring C:\build\Logs\install*.log
The above assumes that there are no directories that match install*.log; if there's a chance of that, pipe the output of Get-ChildItem -File C:\build\Logs -Filter install*.log to Select-String instead.
Do-while will first do the thing, then check the while statement. You're iterating over n files. It doesn't check the value of $count before it executes that portion.
So let's say the first file does not contain the string you're looking for. It will (correctly) decrement the $count variable to zero, and then it moves on to the next $log in $logArr.
Now for each next file in the folder it will decrement $count, and then exit the loop when it sees that $count is not greater than 0.
I don't know why you're using the do-while loop at all here
Thanks Norsk
I over-complicated for myself.
This worked:
$logArr = gci C:\build\Logs | where {($_.name -like 'install*.log') -and (! $_.PSIsContainer)} | select -expand FullName
$count = ($logArr).count
Foreach ($log in $logArr) {
$buildlogsuccess = [bool](select-string -path $log -simplematch $buildstring)
If ($buildlogsuccess) {break}
}

Using Select-String against a server list

I have a serverlist which contains all server names on a single line. Each server has the exact path and file as listed in the following:
$Computers = get-content "c:\temp\serverlist.txt"
foreach ($Computer in $Computers) {
select-string "F:\xxx\SmarXXXX\yyyyyyations\xxxxx\servers\data-sources.xml" `
-pattern "thisiswhatimsearchingfor"
}
I edited the actual code with xxxxx since some of it may be considered sensitive. When I run this command I am given the string that I am looking for, but there is no link to which server returns this data. I essentially need to find out which servers from my serverlist do NOT contain the pattern requested.
Any ideas would be appreciated. Thanks for your patience.
EDIT:
I have come up with the following but it does not display the desired output. This returns just the strings, but not the servers that it is pulling them from. Thanks for the help. I attempted to add the where-object in order to see the associated server with each string. This failed.
$Computers = get-content "c:\temp\serverlist.txt"
foreach ($Computer in $Computers) {
Select-String "F:\xx\xxxxxxPath\applications\yyyyyyy\servers\data-xxxx.xml" -pattern "render" | where {($_ -match "render")
}
}
Use UNC paths and a filter to get a list of computers where the search pattern occurs in the file:
$file = 'F$\xxx\SmarXXXX\yyyyyyations\xxxxx\servers\data-sources.xml'
Get-Content "c:\temp\serverlist.txt" | ? {
(Get-Content "\\$_\$file") -match 'search pattern'
}
This might do it:
Get-Content c:\temp\serverlist.txt | where {
-not ( $_ -match "thisiswhatimsearchingfor" )
}

Using Context in Powershell Select-String

I have a script that searches for a series of strings (stored in a txt file) in the contents of files in a directory. I would like to modify it to also list the text around the string found (these are regular strings, not regex expressions). I played around a lot and it seems like I need to use -Context, but I am not sure how to get the text from that.
Also, the files I am searching may not have linefeeds, so if it could just get the xx characters before and after the search term, that would be better.
Here's what I have so far (I omitted the looping though files parts):
$result = Get-Content $file.FullName | Select-String $control -quiet
If ($result -eq $True)
{
$match = $file.FullName
"Match on string : $control in file : $match" | Out-File $output -Append
Write-host "Match on string : $control in file : $match"
}
If it could write the context, that would be perfect. Seems like I need to use $_Matches, but not sure how.
If $control is just a regular string, can you turn it into a regular expression?
$n = 3
$re = "(.{0,$n})(" + [Regex]::Escape($control) + ")(.{0,$n})"
$result = (Get-Content $file.FullName) -match $re
With this, the $matches hashtable should give you access to the $n characters before and after the match:
if ($result.Length -gt 0) {
echo "Before: $($matches[1])"
echo "After: $($matches[3])"
}
Here is what I have now and it seems to work:
$regex = "[\s\S]{0,$ContextChars}$SearchTerm[\s\S]{0,$ContextChars}"
$results = Get-Content $file.FullName | Select-String -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
if ($results)
{
foreach($result in $results)
{
$display = $result
"File: $file Match ---$display---"
}
}
The only thing I wish I had but don't know how to get it is the line number the match is found on.