Powershell get-content where-object - powershell

Morning, I am new to the world of Windows PowerShell and wondered if someone could advise on the following.
I am searching a txt file for a certain string of text.
Get-Content -Path "filepath" | Where-Object {
$_ -like '*string*'
} | Out-File c:\output.txt
This works OK for me but I want to be a little smarter and only pull back the string for that particular day.
I've tried to use the following
Get-Content -Path "filepath" | Where-Object {
$_ -like Get-Date -DisplayHint Date -UFormat "%d/%m/%y" + '*string*'
} | Out-File c:\output.txt
The line in the text file always starts with the date in that format but then I need to check for a string in the same line?

You need to put the Get-Date in parentheses:
Get-Content -Path "filepath" | Where-Object {
$_ -like (Get-Date -DisplayHint Date -UFormat "%d/%m/%y") + '*string*'
} | Out-File c:\output.txt

So, after trying several attempts, I've noticed that the file I am querying has the date format in MM/dd/yyyy format so this was why I wasn't finding anything.
Also, I needed to look for the previous day as well so added a little bit more in.
Tweaked it slightly and works now
get-content -path "location of text file" | where-object {$_ -like ("{0:MM/dd/yyyy}" -f (get-date).AddDays(-1)) + 'Sqlserver'} | out-file filename
Thanks everyone for your help

Related

Powershell Select-String how to filter by date?

I have a log file that starts with date format, I want to filter out lines that were added in the past 5min and work on them, but when I run my code it gives me wrong data
Log file Syntax
01/12/2020 00:00:00 log info
Code
$referenceTime = '{0:dd/MM/yyyy HH:mm:ss}' -f (Get-Date).AddMinutes(-5)
Get-Content -Path 'C:\..\data.log' |
Where-Object { (($_ -split '\s')[0] + " " + ($_ -split '\s')[1]) -gt $referenceTime } |
ForEach-Object {
#DO SOMETHING..
}
Dates should be compared to other dates, so you should not stringify them.
Try
$referenceTime = (Get-Date).AddMinutes(-5)
Get-Content -Path 'C:\..\data.log' |
Where-Object { $_ -match '^(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2})' } |
Where-Object { [datetime]::ParseExact($matches[1], 'dd/MM/yyyy HH:mm:ss', $null) -gt $referenceTime } |
ForEach-Object {
$_
#DO SOMETHING.. For demo just output the line(s) that matched
}
The first Where-Object matches any line that starts with what looks like a date in the given format and captures that part of the line in $matches[1].
The second Where-Object parses this matched date into a real [DateTime] object, so you can compare it with the date in $referenceTime

Using Powershell to find only those global holidays that occur today

I'm new to using Powershell and I'm trying to scrape a website to find ONLY those global holidays occurring today, using the website below.
https://eresearch.fidelity.com/eresearch/markets_sectors/global/holidayCalendar.jhtml
Here is what I've got so far, any help would be greatly appreciated!
$a = Get-Date -UFormat "%m/%d/%y" #to get the date in mm/dd/yy format
$source = "https://eresearch.fidelity.com/eresearch/markets_sectors/global/holidayCalendar.jhtml"
$result = Invoke-WebRequest $source
$d = $result.AllElements | Where Class -eq "layout-calendar-content-column" | Select -ExpandProperty innerText
echo $d
Ideally, it would only show those holidays that match the date contained in the variable $a.
Your script is almost complete. Instead of your echo statement, try this:
$d -split "`n" | ? { $_ -like "*$a*" }
Update: For your use-case
($d | Out-String) -split "`n" | Where-Object { $_ -like "*$a*" }

The following is not increment the file count correctly Any Clue as to why?

This powershell code searches the directory and outputs a list of all the files and how old they are to a log file that is parsed buy a different script. all that is working correctly but i also need to keep track of the number of files it found for that dir and the number of files found globally. Thats what the two foreach-Object statements do. but they are staying at 0.
gci -filter *.avi | Select-Object Name, #{Name="Age"; Expression= { (((Get-Date) - $_.CreationTime).Days) }} | Where {$_.Age -ge $daysToKeep} | Out-File -filepath $logFile -append | Foreach-Object {$fileCountCam1++} | Foreach-Object {$fileCount++}
mjolinor's solution is valid, but there's another way (if you can use v3). You can use Tee-Object to write to the file without a loop.
You can also combine your two variable increments into the same script block in the final foreach-object which will speed things up significantly.
gci -filter *.avi |
Select-Object Name, #{Name="Age"; Expression= { (((Get-Date) - $_.CreationTime).Days) }} |
Where {$_.Age -ge $daysToKeep} | Tee-Object -filepath $logFile -append |
Foreach-Object {$fileCountCam1++;$fileCount++}
Out-File is a termnating cmdlet (it doesn't ouput the object to the pipeline), so everything after it isn't getting any input from the pipeline.
See if this works better:
gci -filter *.avi |
Select-Object Name, #{Name="Age"; Expression= { (((Get-Date) - $_.CreationTime).Days) }} |
Where {$_.Age -ge $daysToKeep} |
Foreach-Object {
$_ | Out-File -filepath $logFile -append
$fileCountCam1++
$fileCount++
}

Powershell and last modified date

I am working in a windows environment.
I have a project that requires a short script to determine if a file with a modified date of today exists in a folder. If the file exists, it should copy it, if a file does not exist, it should return an error code.
I prefer to not use 3rd party apps. I am considering powershell.
I can pull a list to visually determine if the file exists, but I am having trouble batching to return an error if the count is zero.
Get-ChildItem -Path C:\temp\ftp\archive -Recurse | Where-Object { $_.lastwritetime.month -eq 3 -AND $_.lastwritetime.year -eq 2013 -AND $_.lastwritetime.day -eq 21}
Any help is greatly appreciated!
You can compare the current date against the date part only of each file LastWriteTime short date:
Get-ChildItem -Path C:\temp\ftp\archive -Recurse | Where-Object {
$_.LastWriteTime.ToShortDateString() -eq (Get-Date).ToShortDateString()
}
Get-ChildItem $path -r | % {if((!($_.psiscontianer))-and(Get-Date $_.LastWriteTime -Uformat %D)-eq(Get-Date -UFormat %D)){$_.FullName}else{Write-Warning 'No from Today'}}
F.Y.I. when doing large jobs, like if you'll be going through TB of files, use a foreach-object. It's faster then Where-Object. This method processes the objects collected in the array directly when available and doesn't wait until all objects are collected.
In summary, there always a lot of different ways to achieve the same result in PowerShell. I advocate using what is easiest for you to remember. At the same time, PowerShell can provide some big performance differences between the approaches – and it pays to know more!
You can still make the line a little more efficient by calculating the date
$date = (Get-Date -UFormat %D)
Get-ChildItem $path -r | % {if((!($_.psiscontianer))-and(Get-Date $_.LastWriteTime -Uformat %D)-eq$date){$_.FullName}else{Write-Warning 'No from Today'}}
I was able to use the following script:
$Date = Get-Date
$Date = $Date.adddays(-1)
$Date2Str = $Date.ToString("yyyMMdd")
$Files = gci "C:\\Temp\\FTP\\Archive"
ForEach ($File in $Files){
$FileDate = $File.LastWriteTime
$CTDate2Str = $FileDate.ToString("yyyyMMdd")
if ($CTDate2Str -eq $Date2Str) {Copy-Item $File.Fullname "C:\\Temp\\FTP"; exit}
}
Throw "No file was found to process"
To test if there are no files:
$out = Get-ChildItem -Path C:\temp\ftp\archive -Recurse | Where-Object {
$_.LastWriteTime.ToShortDateString() -eq (Get-Date).ToShortDateString()
};
if ($out.Count -gt 0)
//do something with your output
else
//sorry no file

How do I add a newline to command output in PowerShell?

I run the following code using PowerShell to get a list of add/remove programs from the registry:
Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
| ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") } `
| Out-File addrem.txt
I want the list to be separated by newlines per each program. I've tried:
Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
| ForEach-Object -Process { Write-Output $_.GetValue("DisplayName") `n } `
| out-file test.txt
Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
| ForEach-Object {$_.GetValue("DisplayName") } `
| Write-Host -Separator `n
Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
| ForEach-Object -Process { $_.GetValue("DisplayName") } `
| foreach($_) { echo $_ `n }
But all result in weird formatting when output to the console, and with three square characters after each line when output to a file. I tried Format-List, Format-Table, and Format-Wide with no luck. Originally, I thought something like this would work:
Get-ChildItem -path hklm:\software\microsoft\windows\currentversion\uninstall `
| ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }
But that just gave me an error.
Or, just set the output field separator (OFS) to double newlines, and then make sure you get a string when you send it to file:
$OFS = "`r`n`r`n"
"$( gci -path hklm:\software\microsoft\windows\currentversion\uninstall |
ForEach-Object -Process { write-output $_.GetValue('DisplayName') } )" |
out-file addrem.txt
Beware to use the ` and not the '. On my keyboard (US-English Qwerty layout) it's located left of the 1.
(Moved here from the comments - Thanks Koen Zomers)
Give this a try:
PS> $nl = [Environment]::NewLine
PS> gci hklm:\software\microsoft\windows\currentversion\uninstall |
ForEach { $_.GetValue("DisplayName") } | Where {$_} | Sort |
Foreach {"$_$nl"} | Out-File addrem.txt -Enc ascii
It yields the following text in my addrem.txt file:
Adobe AIR
Adobe Flash Player 10 ActiveX
...
Note: on my system, GetValue("DisplayName") returns null for some entries, so I filter those out. BTW, you were close with this:
ForEach-Object -Process { "$_.GetValue("DisplayName") `n" }
Except that within a string, if you need to access a property of a variable, that is, "evaluate an expression", then you need to use subexpression syntax like so:
Foreach-Object -Process { "$($_.GetValue('DisplayName'))`r`n" }
Essentially within a double quoted string PowerShell will expand variables like $_, but it won't evaluate expressions unless you put the expression within a subexpression using this syntax:
$(`<Multiple statements can go in here`>).
I think you had the correct idea with your last example. You only got an error because you were trying to put quotes inside an already quoted string. This will fix it:
gci -path hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output ($_.GetValue("DisplayName") + "`n") }
Edit: Keith's $() operator actually creates a better syntax (I always forget about this one). You can also escape quotes inside quotes as so:
gci -path hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object -Process { write-output "$($_.GetValue(`"DisplayName`"))`n" }
Ultimately, what you're trying to do with the EXTRA blank lines between each one is a little confusing :)
I think what you really want to do is use Get-ItemProperty. You'll get errors when values are missing, but you can suppress them with -ErrorAction 0 or just leave them as reminders. Because the Registry provider returns extra properties, you'll want to stick in a Select-Object that uses the same properties as the Get-Properties.
Then if you want each property on a line with a blank line between, use Format-List (otherwise, use Format-Table to get one per line).
gci -path hklm:\software\microsoft\windows\currentversion\uninstall |
gp -Name DisplayName, InstallDate |
select DisplayName, InstallDate |
fl | out-file addrem.txt
The option that I tend to use, mostly because it's simple and I don't have to think, is using Write-Output as below. Write-Output will put an EOL marker in the string for you and you can simply output the finished string.
Write-Output $stringThatNeedsEOLMarker | Out-File -FilePath PathToFile -Append
Alternatively, you could also just build the entire string using Write-Output and then push the finished string into Out-File.