PowerShell script to delete lines with timestamp and blank lines - powershell

I'm very new to PowerShell and i'm looking a way to read a file and delete the line if the timestamp is more than 20 days old or blank, and then rewrite it into a new file.
My script is working but if I have a blank line, it fails. Here's the script.
$Culture = [System.Globalization.CultureInfo]::InvariantCulture
$Format = 'dd/MM/yyyy HH:mm:ss'
$Paths = "D:\xxx\yyyy\log.txt","D:\xxx\zzzz\log.txt"
$Day = "20"
Foreach ($Path in $Paths)
{
Get-Content $Path | where { [datetime]::ParseExact(([string]$_).Substring(0,19), $format, $culture) -ge (Get-Date).AddDays(-$Day) } | set-content $Path".new"
}
I try to check if string is null before the where like this
Get-Content $Path | if(!([string]$_)::IsNullOrEmpty) | where { ([datetime]::ParseExact(([string]$_).Substring(0,19), $format, $culture) -ge (Get-Date).AddDays(-$Day)) } | set-content $Path".new"
But it is not working.

if() can't be piped.
You need to use Where-Object similar to the way you already have done:
Get-Content $Path |
Where-Object {$_} |
Where-Object { ([datetime]::ParseExact(([string]$_).Substring(0,19), $format, $culture) -ge (Get-Date).AddDays(-$Day)) } |
Set-Content $Path".new"
Note that {$_} is shorthand for "this has a value"

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

modified date assistance

I have this piece of code that changes a string if it exist. It works perfectly. However, even if the Server1 string doesn't exist in the file it changes the modified date of the file. What I need it to do is if the string Server1 doesn't exist ignore and move on to the remaining files in the folder.
Does anyone here know how I can go about achieving this?
$filenames = Get-ChildItem "C:\test\*.dtsconfig" -Recurse |
select -Expand FullName
foreach ($filename in $filenames) {
(Get-Content $filename) -replace 'Server1', 'Server2' | Set-Content $filename
}
Write the file only if it actually contains the string "Server1":
$txt = Get-Content $filename
if ($txt -like '*Server1*') {
$txt -replace 'Server1', 'Server2' | Set-Content $filename
}
$fileNames = Get-ChildItem "C:\test\*.dtsconfig" -Recurse | Select -Expand FullName
foreach ($filename in $filenames) {
$file = Get-Content $fileName
If ($file -like "*Server1*") {
Get-Content $fileName -replace 'Server1', 'Server2' | Set-Content $fileName
}
}
I've added in an if statement so it checks before making any changes.

Avoid blank line on Out-File

How can I avoid getting a blank line at the end of an Out-File?
$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher([adsi]'')
$DirSearcher.Filter = '(&(objectClass=Computer)(!(cn=*esx*)) (!(cn=*slng*)) (!(cn=*dcen*)) )'
$DirSearcher.FindAll().GetEnumerator() | sort-object { $_.Properties.name } `
| ForEach-Object { $_.Properties.name }`
| Out-File -FilePath C:\Computers.txt
I have tried several options and none of them seem to do anything, they all still have a blank line at the end.
(get-content C:\Computers.txt) | where {$_ -ne ""} | out-file C:\Computers.txt
$file = C:\Computers.txt
Get-Content $file | where {$_.Length -ne 0} | Out-File "$file`.tmp"
Move-Item "$file`.tmp" $file -Force
Use [IO.File]::WriteAllText:
[IO.File]::WriteAllText("$file`.tmp",
((Get-Content $file) -ne '' -join "`r`n"),
[Text.Encoding]::UTF8)
Often when you're looking to see if strings have no character data, you will want to use String.IsNullOrWhiteSpace():
Get-Content $file | Where-Object { ![String]::IsNullOrWhiteSpace($_) } | Out-File "$file`.tmp"
this the best solution for the avoiding the empty line at the end of txt file using powershell command
Add-Content C:\Users\e5584332\Desktop\CSS.txt "Footer | Processed unique data || $count " -NoNewline

Powershell if changed Set-Content

I have a PowerShell script that I use to change text in a number of files. The following script will work & changes the text as expected.
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
(Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
Set-Content $_
}
The problem is though, it changes every file that it opens, so everything has a timestamp of when the job was run even if nothing was changed.
I have tried something similar to what is here but it gives me an error:
The term 'if' is not recognized as the name of a cmdlet, function, etc...
Here is the code I am trying to run:
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
$b = ($a = Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
if (Compare $a $b -PassThru) {
$b | Set-Content $_
}
}
I know that the code isn't right, but if I move it inside the ForEach-Object, it won't run either.
What I want to do is to use the Set-Content statement only if the contents of the file have changed. Would appreciate any thoughts as to how best to do this.
What you can do is look for the string before getting and setting content. Something like:
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
If(Select-String -Path $_ -SimpleMatch $old -quiet){
(Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
Set-Content $_
}
}

Can I pass Parameter using Get-SPWeb andgetting list

i'm using the next code to get list of data from SharePoint and export it to a text file
can i pass parameter to get only data from date to date
something like : Select * between
$MyWeb = Get-SPWeb "http://ilike-eg.suz.itcgr.net/SM"
$MyList = $MyWeb.Lists["SCGC"]
$exportlist = #()
$Mylist.Items | ForEach-Object {
$obj = New-Object PSObject -property #{
"A"=" "+$_["AACCOUNT_ID"]
"B"=" "+$_["BTRANSACTION_ID"]
"C"=" "+$_["CDATE"]
"D"=" "+$_["DCUSTOMER_ID"]
"E"=" "+$_["ECUSTOMER_NAME"]
"F"=" "+$_["FAMOUNT"]
"G"=$_["GCLASS"]
}
#Remove unnecessary sort
$exportlist += $obj
$DateStamp = get-date -uformat "%Y-%m-%d#%H-%M-%S"
$NameOnly = "CDP"
#Exporting with sorted properties
$exportlist |
Select-Object A,B,C,D,E,F,G |
Export-Csv -Delimiter "`t"-path "$NameOnly.txt"
}
#Removed duplicate get-content line
$a, ${d:CDP.txt} = Get-Content .\CDP.txt
#Combined replace statements to avoid multiple read/writes
(Get-Content D:\CDP.txt) |
Foreach-Object {$_ -replace $([char]34) -replace "`t" -replace '/', ''} |
Set-Content D:\CDP.txt
Yes, replace your code:
$Mylist.Items | ForEach-Object {
with something similar to the following code (you need to declare date1 - startDate and date2 - endDate):
$Mylist.Items | where {$_['Created'] -gt $date1 -and $_['Created'] -lt $date2} | ForEach-Object {