December 10, 2009 at 10:07 am
Hi All,
I have just started using powershell and came across a problem:
I have to search for a particluar word/s in all the files of a folder and if a word is matched that file should be moved to a different folder.
I have tried this
get-ChildItem -include *.txt -recurse | select-String -pattern "Msg","Level"
and it gives me the correct output
test.sql.txt:1:Msg 156, Level 15, State 1, Server Line 2
test1.sql.txt:1:Msg 102, Level 15, State 1, Server Line 1
Now I want the above matched files moved to a different folder. How can I do this ?
Also, can I use Powershell to email those files to me ? I know this can be done, but need some help !
Thanks,
\\K
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 11, 2009 at 6:47 am
You'd use Move-Item to move the files. Like this:
get-ChildItem -include *.txt -recurse | select-String -pattern "Msg","Level"|Move-Item -destination [path]
I don't know how to email the files in PowerShell, but I'm sure you can do it.
Jack Corbett
Consultant - Straight Path Solutions
Check out these links on how to get faster and more accurate answers:
Forum Etiquette: How to post data/code on a forum to get the best help
Need an Answer? Actually, No ... You Need a Question
December 11, 2009 at 10:00 am
Jack Corbett (12/11/2009)
You'd use Move-Item to move the files. Like this:
get-ChildItem -include *.txt -recurse | select-String -pattern "Msg","Level"|Move-Item -destination [path]
I don't know how to email the files in PowerShell, but I'm sure you can do it.
Jack .... Thanks for your reply !
This dosen't work! It does not move the files found ! Before posting the topic, I tried the same, but it does not work.
I think I need to use a variable and then use foreach loop, but dont know how to do this !
I refered to http://www.visualbasicscript.com/Using-Powershell-to-Check-Files-m53557.aspx as reference.
Is there any other way of doing that ?
Need help !
Thanks,
\\K
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 11, 2009 at 10:12 am
Sorry but I only have 30 seconds...
The first part is selecting all .txt files (output: file objects).
The second part is selecting each line of text that matches the pattern (output: strings).
The third part is then trying to move these lines of text as if they were files.
I think that you need more than a one liner (it is possible but does that mean you should do it?)
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 11, 2009 at 10:25 am
Gary Istvan Varga (12/11/2009)
Sorry but I only have 30 seconds...The first part is selecting all .txt files (output: file objects).
The second part is selecting each line of text that matches the pattern (output: strings).
The third part is then trying to move these lines of text as if they were files.
Yes Gary, that's what I want and I have managed to do till second part. I need some direction for third part. Like what to use to move those files as Move-Item is not doing that.
I think that you need more than a one liner (it is possible but does that mean you should do it?)
I am a novice in using powershell, as writing codes is what I have starting to learn. 🙂
Thanks for your help,
\\K
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 11, 2009 at 11:30 am
My point is that you cannot take the output from the second part as an input to the third as you are then trying to treat the message lines as they were files.
I have no time to check this but you could do something like the following (there are better ways):
# Deal with each text file in turn
Foreach ($file in get-ChildItem -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = select-String -pattern "Msg","Level"
if (0 < $messages.Length)
{
Move-Item -path $file.FullName -destination [path]
}
}
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 11, 2009 at 12:51 pm
Gary Istvan Varga (12/11/2009)
My point is that you cannot take the output from the second part as an input to the third as you are then trying to treat the message lines as they were files.I have no time to check this but you could do something like the following (there are better ways):
# Deal with each text file in turn
Foreach ($file in get-ChildItem -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = select-String -pattern "Msg","Level"
if (0 < $messages.Length)
{
Move-Item -path $file.FullName -destination [path]
}
}
Thanks so much Gary,
I was trying this to work for days before posting this topic. I modified your hint in case you want to have a look
# Deal with each text file in turn
Foreach ($file in get-ChildItem path -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = $file | select-String -pattern "Msg","Level" |get-ChildItem -name
if (0 -lt $messages.Length )
{
Move-Item -path $file.FullName -destination path
}
}
I changed the comparision operator and the $file variable to pipe to the string match and it worked magic ! 🙂
One more question: Can I email the files as attachment ? can you point some direction ?
Thanks for your time and help,
\\K
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 13, 2009 at 11:05 pm
First off, can I just say thanks to \\K for posting back the real solution (and confirmation that that part works) as this is so much better for the people who come up against the same problem in the future and come across this thread. It is one of my plethora of pet hates when people post a "I've sorted it now." response without saying what the applied resolution was.
Emailing to follow.
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 13, 2009 at 11:20 pm
See Jeffrey Snover comment to this question: http://www.searchmarked.com/windows/how-to-send-an-email-using-a-windows-powershell-script.php
FYI Jeffrey Snover is the MS guy for PowerShell. No Jeffrey Snover, no PowerShell (some of his colleagues will have done a little more than drink cola and eat pizza as well). As an aside, he is a really nice chap to boot!!!
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 14, 2009 at 1:59 pm
Gary Istvan Varga (12/13/2009)
See Jeffrey Snover comment to this question: http://www.searchmarked.com/windows/how-to-send-an-email-using-a-windows-powershell-script.phpFYI Jeffrey Snover is the MS guy for PowerShell. No Jeffrey Snover, no PowerShell (some of his colleagues will have done a little more than drink cola and eat pizza as well). As an aside, he is a really nice chap to boot!!!
Thanks for the link Gary !
That works perfect for email.
One last question. how can I modify the script to move files so that I can run that script and the email script as a whole ?
The reason I am telling is that I want to use the variable $messages as an input to the email script.
The variable $messages --> stores the filenames. So that can be used to send them as attachments.
Below is my script that I have tried so far. It sends email, but without attachment :hehe:
# Deal with each text file in turn
Foreach ($file in get-ChildItem \\servername\foldername\\OutputLogs\ -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = $file | select-String -pattern "Msg","Level" |get-ChildItem -name
if (0 -lt $messages.Length )
{
Move-Item -path $file.FullName -destination "\\servername\foldername\\OutputLogs\Emailed"
}
}
# Send email
$file = $messages
$smtpServer = "SMTP Server Name"
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($file)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "test@domain.com"
$msg.To.Add("test@domain.com")
$msg.Subject = "Test email from scriptrunner-sdb10"
$msg.Body = "This email is send uinsg powershell"
$msg.Attachments.Add($att)
$smtp.Send($msg)
$att.Dispose() #to close the attached file correctly
Thank you again for your time,
\\K 🙂
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 15, 2009 at 12:18 am
Remember that $messages is an array of strings comprised of absolute path filenames. What you are trying to do is add an array as an attachment. You want to do one of the following:
1) send an email for each file:
# Deal with each text file in turn
Foreach ($file in get-ChildItem \\servername\foldername\\OutputLogs\ -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = $file | select-String -pattern "Msg","Level" |get-ChildItem -name
if (0 -lt $messages.Length )
{
Move-Item -path $file.FullName -destination "\\servername\foldername\\OutputLogs\Emailed"
}
}
# Send email for each selected text file in turn
Foreach ($filename in $messages)
{
$smtpServer = "SMTP Server Name"
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mailn.Attachment($filename)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "test@domain.com"
$msg.To.Add("test@domain.com")
$msg.Subject = "Test email from scriptrunner-sdb10"
$msg.Body = "This email is send uinsg powershell"
$msg.Attachments.Add($att)
$smtp.Send($msg)
$att.Dispose() #to close the attached file correctly
}
2) send one email with each file attached:
# Deal with each text file in turn
Foreach ($file in get-ChildItem \\servername\foldername\\OutputLogs\ -include *.txt -recurse)
{
# Assuming it is an array returned
$messages = $file | select-String -pattern "Msg","Level" |get-ChildItem -name
if (0 -lt $messages.Length )
{
Move-Item -path $file.FullName -destination "\\servername\foldername\\OutputLogs\Emailed"
}
}
# Send email
$smtpServer = "SMTP Server Name"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "test@domain.com"
$msg.To.Add("test@domain.com")
$msg.Subject = "Test email from scriptrunner-sdb10"
$msg.Body = "This email is send uinsg powershell"
$attachments = new-object Net.Mail.Attachment[] $messages.Length
Foreach ($count = 0; $count -lt $messages.Length; $count++)
{
$attachments[count] = new-object Net.Mail.Attachment($messages[count])
$msg.Attachments.Add($attachments[count])
# Can do following after loop? $msg.Attachments.Add($attachments)
}
$smtp.Send($msg)
Foreach ($attachment in $attachments)
{
$attachment.Dispose() #to close the attached file correctly
}
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 15, 2009 at 11:39 am
Gary,
I am using your 2nd code as that will send less emails to the team with all files attached, but I am getting following error:
Missing 'in' after variable in foreach loop. file.ps1:24 char:17 + Foreach ($count - <<<< eq 0; $count -lt $messages.Length; $count++)
I checked the syntax and what you have mentioned in 2 is all correct ! I dont know why it is complaining about "in" ?
Any ideas :w00t:
Edit ***
I tried comenting out some stuff like below to figure out where the problem is :
# Send email
$smtpServer = "SMTPServerName"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "test@domain.com"
$msg.To.Add("test@domain.com")
$msg.Subject = "Test email from database"
$msg.Body = "This email is send uinsg powershell"
$attachments = new-object Net.Mail.Attachment[] $messages.Length
#Foreach ($count -eq 0; $count -lt $messages.Length; $count++)
#{
# $attachments[count] = new-object Net.Mail.Attachment($messages[count])
# $msg.Attachments.Add($attachments[count])
# break
# # Can do following after loop? $msg.Attachments.Add($attachments)
#}
$smtp.Send($msg)
#Foreach ($attachment in $attachments)
#{
# $attachment.Dispose() #to close the attached file correctly
#}
This gives me an error
New-Object : Constructor not found. Cannot find an appropriate constructor for
type Net.Mail.Attachment[].
At S:\emailtest.ps1:10 char:26
+ $attachments = new-object <<<< Net.Mail.Attachment[] $messages.Length
Also, using your first script ,the email is sent but no attachment and on powershell screen, I am getting following errors:
New-Object : Constructor not found. Cannot find an appropriate constructor for
type Net.Mail.Attachment.
At S:\emailtest.ps1:20 char:21
+ $att = new-object <<<< Net.Mail.Attachment($filename)
Exception calling "Add" with "1" argument(s): "Value cannot be null.
Parameter name: item"
At S:\emailtest.ps1:27 char:24
+ $msg.Attachments.Add( <<<< $att)
You cannot call a method on a null-valued expression.
At S:\emailtest.ps1:29 char:16
+ $att.Dispose( <<<< ) #to close the attached file correctly
Edit *******
I have used the below code to send email with attachments, but it sends all the files present in the folder .... I want to send only the files that are moved to the folder
$smtpServer = "SMTP Server Name"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "test@domain.com"
$msg.To.Add("test@domain.com")
$msg.Subject = "Email with attachment"
$msg.Body = "Powershell sending email with files attached"
foreach ($file in gci "\\servername\OutputLogs\Emailed"){
$att = New-Object Net.Mail.Attachment($file.fullname)
$msg.Attachments.Add($att)
}
$smtp.Send($msg)
I know I am missing something ... but cant figure out :hehe:
Thanks,
\\K
______________________________________________________________________________________________________________________________________________________________________________________
HTH !
Kin
MCTS : 2005, 2008
Active SQL Server Community Contributor 🙂
December 15, 2009 at 11:25 pm
Sorry. In my haste I have been a complete and utter Muppet.
When I wrote:
Foreach ($count -eq 0; $count -lt $messages.Length; $count++)
it should have been:
For ($count -eq 0; $count -lt $messages.Length; $count++)
It is a For loop not a ForEach loop.
For the lawyers: Muppet is a trandmark of The Jim Henson Company.
For my friends: acting like a Muppet is a trademark of Gary Varga.
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 15, 2009 at 11:51 pm
Removed duplicate post (browser issue).
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
December 16, 2009 at 12:04 am
Next...
I was being silly with arrays (been a while since I've done serious PowerShell).
Instead of
$attachments = new-object Net.Mail.Attachment[] $messages.Length
and
$attachments[count] = new-object Net.Mail.Attachment($messages[count])
$msg.Attachments.Add($attachments[count])
try
$attachments = @()
and
$attachment = new-object Net.Mail.Attachment($messages[count])
$attachments = $attachments + $attachment
$msg.Attachments.Add($attachment)
or even better by replacing
Foreach ($count = 0; $count -lt $messages.Length; $count++)
{
$attachments[count] = new-object Net.Mail.Attachment($messages[count])
$msg.Attachments.Add($attachments[count])
# Can do following after loop? $msg.Attachments.Add($attachments)
}
with
Foreach ($message in $messages)
{
$attachment = new-object Net.Mail.Attachment($message)
$attachments = $attachments + $attachment
$msg.Attachments.Add($attachment)
# Can do following after loop? $msg.Attachments.Add($attachments)
}
Gaz
-- Stop your grinnin' and drop your linen...they're everywhere!!!
Viewing 15 posts - 1 through 15 (of 19 total)
You must be logged in to reply to this topic. Login to reply