Get-Date less than date/string from text file - powershell

I have written some code that parses warranty information about a license from a website into a .txt file. My goal (and problem) is to compare the warranty expiry date from a .txt file with the current date, in order to know if warranty has expired.
I am a powershell beginner so my code might not be very logical, but this is what I have so far:
#the Invoke-WebRequest is up here which outputs into $output_file
#files
$output_file = ‘c:\warrantyinfo.txt’
$warranty_file = 'c:\warrantydate.txt'
#At this point all the warranty information is in $output_file
#With the code below I do a select string to get the information I want and
#get rid of everything else
$warrantyUntil = Get-Content $output_file
$warrantyUntil | Select-String '("toCustomerDate":)["]\d{4}\-(0?[1-
9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*' -AllMatches | Foreach-Object
{$_.Matches} | Select value > $warranty_file
#I now have "toCustomerDate":"yyyy-mm-dd in a new .txt file
#Below I try to grab just the date in the format yyyy-mm-dd in order to
#compare with todays date. I think this is where I go wrong.
$warrantyDate=Select-String -Path $warranty_file -Pattern "\d{4}\-(0?[1-
9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*" -AllMatches | Foreach-Object
{$_.Matches} | Select value
#Current date in the format I want
$currentDate=Get-Date -UFormat "%Y-%m-%d"
#Compare warrantyDate and currentDate to decide if warranty has expired or
#not
if ($currentDate -lt $warrantyDate) {
Write-Host "Warranty is valid"
} else {
Write-Host "Warranty has expired"
}

This is happens because of data type mismatch.
First of all your $currentDate is a string type, while you probably wanted it to be datetime type, this is happening because of performed specific formatting. Also $warrantyDate is string or even an array of strings. You need to take that in mind too.
You would want to explisitly set data type of initializtion variable by placing proper class acceleration before variable name. Like so:
[DateTime]$currentDate=Get-Date -UFormat "%Y-%m-%d"
[DateTime]$warrantyDate=Select-String -Path $warranty_file -Pattern "\d{4}\-(0?[1-
9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])*" -AllMatches | Foreach-Object
{$_.Matches} | Select value
To see what is variable type use this:
$currentDate.GetType().Name

With a file warrantyinfo.txt:
"toCustomerDate":"2018-04-22"
"toCustomerDate":"2018-04-24"
and this script:
$currentDate=Get-Date
$output_file = ‘.\warrantyinfo.txt’
$warrantyUntil = Get-Content $output_file |
Select-String '(?<="toCustomerDate":)"\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])"' -AllMatches
$warrantyUntil
$warrantyUntil.matches.value
$warrantyUntil.matches.value | ForEach {
if ($currentDate -lt [datetime]$_.trim('"')) {
Write-Host "Warranty $_ is valid"
} else {
Write-Host "Warranty $_ has expired"
}
}
You'll get this sample output:
"toCustomerDate":"2018-04-22"
"toCustomerDate":"2018-04-24"
"2018-04-22"
"2018-04-24"
Warranty "2018-04-22" has expired
Warranty "2018-04-24" is valid
The script uses a different RegEx with a positive LookBehind assertion for (?<="toCustomerDate":) which isn't part of matched value.

Related

Powershell Files fetch

Am looking for some help to create a PowerShell script.
I have a folder where I have lots of files, I need only those file that has below two content inside it:
must have any matching string pattern as same as in file file1 (the content of file 1 is -IND 23042528525 or INDE 573626236 or DSE3523623 it can be more strings like this)
also have date inside the file in between 03152022 and 03312022 in the format mmddyyyy.
file could be old so nothing to do with creation time.
then save the result in csv containing the path of the file which fulfill above to conditions.
Currently am using the below command that only gives me the file which fulfilling the 1 condition.
$table = Get-Content C:\Users\username\Downloads\ISIN.txt
Get-ChildItem `
-Path E:\data\PROD\server\InOut\Backup\*.txt `
-Recurse |
Select-String -Pattern ($table)|
Export-Csv C:\Users\username\Downloads\File_Name.csv -NoTypeInformation
To test if a file contains a certain keyword from a range of keywords, you can use regex for that. If you also want to find at least one valid date in format 'MMddyyyy' in that file, you need to do some extra work.
Try below:
# read the keywords from the file. Ensure special characters are escaped and join them with '|' (regex 'OR')
$keywords = (Get-Content -Path 'C:\Users\username\Downloads\ISIN.txt' | ForEach-Object {[regex]::Escape($_)}) -join '|'
# create a regex to capture the date pattern (8 consecutive digits)
$dateRegex = [regex]'\b(\d{8})\b' # \b means word boundary
# and a datetime variable to test if a found date is valid
$testDate = Get-Date
# set two variables to the start and end date of your range (dates only, times set to 00:00:00)
$rangeStart = (Get-Date).AddDays(1).Date # tomorrow
$rangeEnd = [DateTime]::new($rangeStart.Year, $rangeStart.Month, 1).AddMonths(1).AddDays(-1) # end of the month
# find all .txt files and loop through. Capture the output in variable $result
$result = Get-ChildItem -Path 'E:\data\PROD\server\InOut\Backup'-Filter '*.txt'-File -Recurse |
ForEach-Object {
$content = Get-Content -Path $_.FullName -Raw
# first check if any of the keywords can be found
if ($content -match $keywords) {
# now check if a valid date pattern 'MMddyyyy' can be found as well
$dateFound = $false
$match = $dateRegex.Match($content)
while ($match.Success -and !$dateFound) {
# we found a matching pattern. Test if this is a valid date and if so
# set the $dateFound flag to $true and exit the while loop
if ([datetime]::TryParseExact($match.Groups[1].Value,
'MMddyyyy',[CultureInfo]::InvariantCulture,
[System.Globalization.DateTimeStyles]::None,
[ref]$testDate)) {
# check if the found date is in the set range
# this tests INCLUDING the start and end dates
$dateFound = ($testDate -ge $rangeStart -and $testDate -le $rangeEnd)
}
$match = $match.NextMatch()
}
# finally, if we also successfully found a date pattern, output the file
if ($dateFound) { $_.FullName }
elseif ($content -match '\bUNKNOWN\b') {
# here you output again, because unknown was found instead of a valid date in range
$_.FullName
}
}
}
# result is now either empty or a list of file fullnames
$result | set-content -Path 'C:\Users\username\Downloads\MatchedFiles.txt'

Powershell Select-String

I need your help with PowerShell.
I need Select-String with fixed Date (in variable). & Set-Content to result.txt
Example: $Date = "01.07.2020"
But also i need select string with date which lower than i written in variable.
My code: Get-Content -Path log.txt | Select-String "?????" | Set-Content $result.txt
In log.txt i have many strings like " Creation date 01.07.2020 " ; " Creation date 01.06.2020 "
123.txt
Creation date 01.07.2020
Creation date 02.05.2020
Creation date 01.06.2020
Creation date 28.08.2020
Example script
$file = "C:\Users\userprofile\Desktop\test\123.txt"
$regexpattern = "\d{2}\.\d{2}\.\d{4}"
$content = Get-Content $file | Where-object { $_ -match $regexpattern}
foreach($line in $content){
$line.Substring(13,11)
}
I used regex to find the lines you are wanting to output. We get the content only if it matches our regex, then for each line we found, I'm using substring to pull the date out. You could also put together a regex for this if you wanted to. Since we know the lines have the same number of characters it's safe to use the substring function.
If you want that output to a file, simply find $line.Substring(13,11) and then add this after it | Out-file "C:\Users\userprofile\desktop\test\output.txt" -append.

Find and replace strings in files in a given date range by filename

A nice tough one for you all. I'm trying to find and replace a given string in a bunch of files. The files have a date stamp in the file name i.e. YYYY_MM_DD_file.txt
I wish to search and replace within a date range for these files and then replace a string I define, I cannot use date modified as the date range, I must rely on the stamp in the filename.
So far I set my date range in WPF text fields:
$Filename = $Filenamebox.text
$startdate = [datetime] $startdatetext.text
$enddate = [datetime] $enddatetext.Text
$NewFilenamereal = $Newfilename.Text
$array =
do {
$startdate.ToString('yyyy_MM_dd*')
$startdate = $startdate.AddDays(1)
}
until ($startdate -gt [datetime] $enddate)
$files1 = $array | foreach-object {"C:\Users\michael.lawton\Desktop\KGB\Test folder\$_"}
write-host $files1
I then get child items using the $files1 array I have created as a search mask for the files in the date range and find all matches. Store this in a variable and replace the string $filename with the new string $Newfilenamereal.
$Matches1 = get-childitem $files1 | select-string $Filename | foreach-object {$_ -replace $Filename,$Newfilenamereal} | out-string
write-host $Matches1
However I cannot work out how to overwrite what has been found and replaced in the $Matches1 variable to the original files. I have tried set-content, however this will simply either erase everything I have in the date stamped files or cannot understand the $files1 array as a file path.
So my question to you lovely people is how do I write what I have replaced in the environment to the actual files?
Just retrieve the file content using the Get-Content cmdlet and replace the string. Finally write it back using the Set-Content cmdlet:
Get-ChildItem $files1 | ForEach-Object {
($_ | Get-Content -Raw) -replace $Filename,$Newfilenamereal |
Set-Content -Path $_.FullName -Encoding UTF8
}

Finding entries in a log file greater than a defined time

My company needs to analyse log files of a Tomcat to check for specific errors and uses Powershell. Those errors will be stored in an array and checked against 1:1. This happens every 30 minutes by using Windows Task Scheduler. In case such an error is found in the log file, a generated text file will be sent to the administrators.
However it is only of interest to check for errors during the last 30 minutes, not beforehand.
So I have defined first a variable for the time:
$logTimeStart = (Get-Date).AddMinutes(-30).ToString("yyyy-MM-dd HH:mm:ss")
Later on I check for the existence of such an error:
$request = Get-Content ($logFile) | select -last 100 | where { $_ -match $errorName -and $_ -gt $logTimeStart }
Unfortunately this does not work; it also sends errors happened before this interval of 30 minutes.
Here is an extract of the Tomcat log:
2016-05-25 14:21:30,669 FATAL [http-apr-8080-exec-4] admins#company.de de.abc.def.business.service.ExplorerService GH00000476:
de.abc.def.business.VisjBusinessException: Invalid InstanceId
at de.abc.def.business.service.ExplorerService$ExplorerServiceStatic.getExplorer(ExplorerService.java:721)
at de.abc.def.business.service.ExplorerService$ExplorerServiceStatic.getTreeItemList(ExplorerService.java:823)
at sun.reflect.GeneratedMethodAccessor141.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at de.abc.def.business.provider.ServiceProvider.callServiceMethod(ServiceProvider.java:258)
at de.abc.def.business.communication.web.client.ServiceDirectWrapperDelegate.callServiceMethod(ServiceDirectWrapperDelegate.java:119)
at de.abc.def.business.communication.web.client.ServiceWrapperBase.callServiceMethod(ServiceWrapperBase.java:196)
at de.abc.def.business.communication.web.client.ServiceDirectWrapper.callServiceMethod(ServiceDirectWrapper.java:24)
at de.abc.def.web.app.service.stub.AbstractBaseStub.callServiceMethodDirect(AbstractBaseStub.java:72)
at de.abc.def.web.app.service.stub.AbstractBaseStub.callServiceMethod(AbstractBaseStub.java:183)
at de.abc.def.web.app.service.stub.StubSrvExplorer.getTreeItemList(StubSrvExplorer.java:135)
at de.abc.def.web.app.resource.servlet.ExplorerServlet.createXml(ExplorerServlet.java:350)
at de.abc.def.web.app.resource.servlet.ExplorerServlet.callExplorerServlet(ExplorerServlet.java:101)
at de.abc.def.web.app.resource.servlet.VisServlet.handleServlets(VisServlet.java:244)
at de.abc.def.web.app.FlowControlAction.isPing(FlowControlAction.java:148)
at de.abc.def.web.app.FlowControlAction.execute(FlowControlAction.java:101)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
Unfortunately one cannot say how many lines of such an error will show up. Therefore 100 is just an estimate (which works well).
So how to change the related line
$request = Get-Content ($logFile) | select -last 100 |
where { $_ -match $errorName -and $_ -gt $logTimeStart }
to a correct one?
Use Select-String and a regular expression to parse your log file. Basically a log entry consists of a timestamp, the severity, and a message (which may span several lines). A regular expression for that might look like this:
(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})\s+(\w+)\s+(.*(?:\n\D.*)*(?:\n\t.*)*)
(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) matches the timestamp.
(\w+) matches the severity.
(.*(?:\n\D.*)*) matches the log message (the current line followed by zero or more lines not beginning with a number).
The parentheses around each subexpression capture the submatch as a group that can then be used for populating the properties of custom objects.
$datefmt = 'yyyy-MM-dd HH:mm:ss,FFF'
$culture = [Globalization.CultureInfo]::InvariantCulture
$pattern = '(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})\s+(\w+)\s+(.*(?:\r\n\D.*)*)'
$file = 'C:\path\to\your.log'
Get-Content $file -Raw | Select-String $pattern -AllMatches | ForEach-Object {
$_.Matches | ForEach-Object {
New-Object -Type PSObject -Property #{
Timestamp = [DateTime]::ParseExact($_.Groups[1].Value, $datefmt, $culture)
Severity = $_.Groups[2].Value
Message = $_.Groups[3].Value
}
}
}
Parsing the date substring into a DateTime value isn't actually required (since date strings in ISO format can be sorted properly even with string comparisons), but it's nice to have so you don't have to convert your reference timestamp to a formatted string.
Note that you need to read the entire log file as a single string for this to work. In PowerShell v3 and newer this can be achieved by calling Get-Content with the parameter -Raw. On earlier versions you can pipe the output of Get-Content through the Out-String cmdlet to get the same result:
Get-Content $file | Out-String | ...

Check text file content in 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"
}