Windows powershell file process duplication - powershell

My folder structure is "C:\Temp\SalesOrder\20160809\cc.txt" when its looking for all the files that need to be processed as soon as the recursion gets to folder "C:\Temp\SalesOrder" & "C:\Temp\SalesOrder\20160809" its processing cc.txt file. How do I rewrite the gci to not to traverse subfolders and only process files "C:\Temp\SalesOrder\20160809"
$flatFilePath = "C:\Temp\Email.csv"
$flatFile = Import-Csv -Path $flatFilePath -Header Dir,Email
$emailID = #{}
foreach ($record in $flatFile) { $emailID[$record.Dir]=$record.Email }
# organization folder
$orgFolder = Get-ChildItem -Path "C:\Temp\" -Recurse -Exclude *.*
# Send email
foreach ($dir in $orgFolder) {
$processedfiles = $null
$emailTo = $null
Get-ChildItem -Path $dir.FullName -Recurse -Include *.txt,*.xls,*.csv,*.xlsx | ? { $_.FullName } |
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}
$emailTo = $emailID.Get_Item($dir.Name) -split ";"
if ($processedfiles) { Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body "$Body $processedfiles" -SmtpServer $SMTPServer -port $SMTPPort }
}
Problem area:
Get-ChildItem -Path $dir.FullName -Recurse -Include *.txt,*.xls,*.csv,*.xlsx | ? { $_.FullName } |
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}

You can use regex to only select Folders which have the date structure
$orgFolder = Get-ChildItem -Path 'C:\Temp\' -Recurse -Exclude *.*
$orgfolder = $orgfolder -match '(\\(\d{2})(\d{2})(\d{2})(\d{2}))'

As I understand your problem, you have the right code with a small bug.
In your loop...
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}
... you concatenate the file names, instead of the $internalOrg variables, where you extracted the folder name.
It should be the following if you want the folders:
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($internalOrg) + " | ";
}

Related

If path does not exist, skip FOREACH

I have a question that I hope one of you can help me with.
The following script does its job, it sends the email of the folders that are older than 30 days.
I want to add 2 more features...
If the OwnerEmail.txt is not there or empty.. it will not send the email.
If there are not folders older than 30 days, it will not send the email.
I am just having problems using the CONTINUE feature to skip the ForEach
$ParentFolders = Get-ChildItem -Path "C:\Test\WRA" -Directory |
Select-Object -ExpandProperty FullName
foreach ($SubFolder in $ParentFolders) {
$Contact = Get-Content -Path ($SubFolder + "\OwnerEmail.txt")
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-30))} |
Select-Object Name, CreationTime |
ConvertTo-Html -Head $Header -PreContent "
<h2>Current Nuix Case(s)</h2>
<body>
Report was sent on $emailTime
<br></br>
When you have a moment can you please confirm if any of these cases can be removed from Nuix:
<body>
<br></br> " |
$WRAHTMLReport = $WRAHTMLReport -join ""
Start-Sleep -s 2
Send-MailMessage -SmtpServer mail.company.com -to $Contact -from cubam1#company.com -Subject "Nuix Cases" -Body $WRAHTMLReport -BodyAsHtml
}
So, it could look something like this, note that I'm only showing the relevant parts of the code.
I think in this case, is safe to put the $emailTime outside the loop since you're only gathering the date in MM/dd/yyyy format and, I also added the $folderLimitDate outside the loop.
This variable contains the HTML body
$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport... so remember to change the -Body $mailBody on Send-MailMessage
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$folderLimitDate = (Get-Date).AddDays(-30)
foreach ($SubFolder in $ParentFolders)
{
$path = Join-Path $SubFolder -ChildPath 'OwnerEmail.txt'
# If OwnerEmail.txt doesn't exist on this path,
# go to next loop iteration
if(-not(Test-Path $path)){ continue }
$Contact = Get-Content $path
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object LastWriteTime -LT $folderLimitDate |
Select-Object Name, CreationTime
# If this variable is null, go to next loop iteration
if(-not $WRAHTMLReport){ continue }
[string]$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport...
...
...
...

Powershell- Delete files older then x days and send only email after files are deleted

how to delete files older then x days and send only email notification, if files are deleted by script. Here is my script.. files are deleted by script, but email notification is not working. If I delete the if clauses (if(!$messageBody)) then email notification is working, but I am getting email when no files are deleted, too.
Get-ChildItem temp*.zip -Path "c:\tempfiles" |
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-0) }|
ForEach-Object {
$_ | Remove-Item -force
-join $([datetime]::Now) + " " + $_.Name| Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$OF = "`r`n"
$messageBody = $_.Name + $OF + $messageBody
}
$date = ( get-date )
if(!$messageBody){
$smtpServer = ""
$smtpFrom = ""
$smtpTo = ""
$server = ""
$messageSubject = "Subject $server - $date"
$body= "files"
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
$messageBody=" "
}
You can do the following to find temp*.zip files, delete them, log the deleted files to a log file, and then email a list of deleted files. This assumes your deletions are successful. You will need to remove the -WhatIf parameter for deletions to occur.
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File -OutVariable files | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
If you want error checking and only report when files are deleted, you can make some modifications.
$files = [Collections.Generic.List[String]]#()
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
if ($?) {
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$files.Add($_.Name)
}
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
$? returns true if the last command executed successfully. See About_Automatic_Variables.
The syntax #MailParams is called Splatting. It is simply used here for readability.

List all files that were moved in an email Body - Powershell

Trying to accomplish the following:
1)Move files from multiple sources into multiple destinations.
Therefore i listed sources under a SOURCE column, and destinations under a DESTINATION column (WORKING)
2)Send an email with a list of files that were moved and the destination (Not working)
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination))
{
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination -WhatIf
}
# Copy file
$MoveFileprocess = Move-Item -Path $_.Source -Destination $_.Destination -force -PassThru
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
$SMTPBody = "`nThe following files have recently been added `n
$MoveFileprocess `n"
Send-MailMessage #SMTPMessage -Body $SMTPBody
Right now its listing all the files in one single line, hard to read
I was wondering if theres a way to send the body email as
File 1 moved to Destination 1
File 2 moved to Destination 2
and so on...
You were pretty close. Try this:
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
$SMTPBody = "`nThe following files have recently been added `n"
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination)){
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination
}
If((Get-Item $_.Source).LastWriteTime -gt (Get-Item $_.Destination).LastWriteTime){
Move-Item -Path $_.Source -Destination $_.Destination -force
$SMTPBody += "$($_.Source) moved to $($_.Destination)`n"
}Else{
Write-Warning "Skipped overwriting newer $($_.Destination)"
}
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
Send-MailMessage #SMTPMessage -Body $SMTPBody
Note that Move-Item -PassThru returns the affected object, not a string. I took out the -WhatIf parameter for the New-Item command, indented the foreach{} loop and made indenting and brackets consistent.

Powershell script that checks if a file is X Days old and alert me via email

I have the below script and it works, i want it to be able to send me an email if my file is 2 days old. I'm not sure how to get the email part working.
Thank you
$fullPath = "\\test\avvscan.dat"
$numdays = 2
$numhours = 1
$nummins = 1
function ShowOldFiles($path, $days, $hours, $mins)
{
$files = #(get-childitem $path -include *.* -recurse | where
{($_.LastWriteTime -lt (Get-Date).AddDays(-$days).AddHours(-$hours).AddMinutes(-$mins)) -and
($_.psIsContainer -eq $false)})
if ($files -ne $NULL)
{
for ($idx = 0; $idx -lt $files.Length; $idx++)
{
$file = $files[$idx]
write-host ("Old: " + $file.Name) -Fore Red
}
}
}
ShowOldFiles $fullPath $numdays $numhours $nummins
Something like this perhaps:
$fullPath = "\\test\avvscan.dat"
$numdays = 2
$numhours = 1
$nummins = 1
function Get-OldFiles($path, $days, $hours, $mins) {
$refDate = (Get-Date).AddDays(-$days).AddHours(-$hours).AddMinutes(-$mins)
Get-ChildItem $path -Recurse -File |
Where-Object {($_.LastWriteTime -lt $refDate)} |
ForEach-Object {
Write-Host ("Old: " + $_.FullName) -ForegroundColor Red
# emit an object containing the interesting parts for your email
[PSCustomObject]#{
'File' = $_.FullName
'LastWriteTime' = $_.LastWriteTime
}
}
}
$oldFiles = #(Get-OldFiles $fullPath $numdays $numhours $nummins)
if ($oldFiles.Count) {
# send an email if there are old files found
$body = $oldFiles | Format-Table -AutoSize | Out-String
# look for more options here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-3.0
Send-MailMessage -From "someone#yourdomain.com" -To "you#yourdomain.com" -SmtpServer "your.smtp.server" -Subject "Old files in $fullPath" -Body $body
}

Read folder content and finds lastwritetime of today if finds file which was lastwritetime of today email it

I have a folder which a log is written to it any time a job fails, the folder contains all older logs as well. The goal is to send an email to user on daily basis with the log file generated. If the log found, sends the file in attachment, else sends an email stating file not found. I put below script but the problem is that it reads all files, even though there is only one log file for today.
$TodaysDate = (Get-Date).DayOfYear
$LogPath = "C:\Temp\Error"
$filename = Get-ChildItem -Path "C:\temp\Error"
foreach ($file in $LogPath) {
$fileDate = ($file.LastWriteTime).DayOfYear
if ($fileDate -eq $TodaysDate) {
$fileName = $file.Name
}
}
$LogFile = $LogPath + $filename
$LogFileName = $LogFile | ? {Test-Path $LogFile} | Get-ChildItem |
Where-Object { $_ -is [System.IO.FileInfo] }
$MessageBodyNA = "Email from task scheduler. No log file found" + $filename
$MessageBodyA = "Email from task scheduler. File" + $LogFileName +
" found and attached"
#
$FromAddress = "test#gmail.com"
#
$ToAddress = "test#gmail.com"
$Subject = "Bad log"
# SMTP server name
$SMTPserver = "smtp.test"
# check if attachment file exists if so email with attachment else without
# attachment
if ( $LogFileName | Where-Object { $_ -is [System.IO.FileInfo] }) {
send-mailmessage -from $FromAddress -to $ToAddress -subject $Subject `
-body $MessageBodyA -smtpServer $SMTPserver -Attachments $LogFileName
} else {
send-mailmessage -from $FromAddress -to $ToAddress -subject $Subject `
-body $MessageBodyNA -smtpServer $SMTPserver
}
Your routine to determine the file is totally convoluted. Change this:
$TodaysDate = (Get-Date).DayOfYear
$LogPath = "C:\Temp\Error"
$filename = Get-ChildItem -Path "C:\temp\Error"
foreach ($file in $LogPath) {
$fileDate = ($file.LastWriteTime).DayOfYear
if ($fileDate -eq $TodaysDate) {
$fileName = $file.Name
}
}
$LogFile = $LogPath + $filename
$LogFileName = $LogFile | ? {Test-Path $LogFile} | Get-ChildItem |
Where-Object { $_ -is [System.IO.FileInfo] }
into this:
$LogPath = "C:\Temp\Error"
$LogFileName = Get-ChildItem $LogPath | ? {
-not $_.PSIsContainer -and
$_.LastWriteTime.Date -eq (Get-Date).Date
}