Scan a Folder For Changes
Another fun little project popped up at Spiceworks yesterday. OP (Original Poster) was looking to create a vbScript that would scan a folder for new files. The Folder was actually part of an FTP site he had setup and he wanted to be notified by email whenever something new was uploaded to it. Here’s how I went after the script.
So how do you figure out new files have been uploaded into a Folder? There are a few things you can do. One is you can save all of the filenames into a database/text file, then compare that file to what’s actually in the folder, if there’s a difference you have a hit! Another method is you can use Windows event handling and actually trigger the script whenever there is a change. But there is another way that turns out to be the easiest. The script runs every 10 minutes, so we could do a simple search for files that have been updated in the past 10 minutes. If we get a hit we get notified. Now, you could edit a file and trigger the script too but in this case I believe that’s acceptable.
Turns out the actual code to detect a changed file in the past 10 minutes is pretty easy:
Get-ChildItem * | where ( $_.LastWriteTime -ge [datetime]::Now.AddMinutes(-10) }
You use Get-ChildItem to scan for all files in the folder you want (if you want to scan sub-folders too you would add the -recurse parameter) then pipe it into the Where cmdlet where you check the .LastWriteTime with the time right now minus 10 minutes.
Ryan Witschger made a great comment in his blog about declaring all of his variable as Parameters, which is a great idea. By doing that it allows you to really make your script flexible as you can change these values on the fly and even run your script in multiple ways without changing code. If you’ve ever had a script that you run for different things and then have to update that script “x” times because you made an update to it you know what I mean! So on this script let’s declare some variables.
Param ( [string]$Path = "D:\FTPSites\", [string]$SMTPServer = "smtpservername", [string]$From = "SFTPAlert@domain.com", [string]$To = "user@domain.com", [string]$Subject = "New File Uploaded to FTP Site" )
Since we’re sending an email we want to use the Send-MailMessage cmdlet to accomplish that. Now, you could just run it with every property you need and the variables you’ve declared above but honestly it makes for pretty ugly looking code. A nice workaround for that is a method called “splatting“. In a nutshell you create a hash table with all of the properties you want to use, then when you call the Send-MailMessage cmdlet you use your hash table with a “@” symbol and that will apply the table as your properties. Here’s how:
$SMTPMessage = @{ To = $To From = $From Subject = "$Subject at $Path" Smtpserver = $SMTPServer } Send-MailMessage @SMTPMessage
Notice the Subject line? I love the fact that in Powershell you don’t have to break out of a string to add variables within the text. Such a time saver!
Now we’ve got all of our files located (if any), we’ve got the header information for our Send-MailMessage cmdlet, we just need the body. For me, looks are everything so let’s have the script notify you that not only have files been uploaded, but which ones. You’ll notice some odd code in the string declarations: “`n“. The back tick character is the Powershell escape character, this allows you to put in reserved characters like the $ sign or the hash simple # in a string (which Powershell will try to interpret as a variable or comment) or you can also add special characters. `n is a carriage return or new line.
If ($File) { $SMTPBody = "`nThe following files have recently been uploaded to your FTP site:`n`n" $File | ForEach { $SMTPBody += "$($_.FullName)`n" }
We start by assigning a variable some simple information about what’s happened, then loop through all of the objects in $File and put the FullName property–which is the full path of the file.
And there you have it. Create a scheduled task and run Powershell.exe as your program, and the following as the argument:
-ExecutionPolicy Bypass <pathtoscript>\Scan-FolderForFiles.ps1
You’ve also decided that you want to scan a folder on the file server called Suggestion Box and anytime someone places a file in there to email HR. Schedule another task (doesn’t have to be on the file server) with these parameters:
<pathtoscript>\Scan-FolderForFiles.ps1 -Path "\\<fileserver>\<share>\Suggestion Box" -From SuggestionBox@domain.com -Subject "New File in Suggestion Box" -To HR@domain.com
This will override the Path, From, To and Subject fields while leaving the SMTPServer (your SMTP relay) field alone.
Here’s the full code with a little change to make some of the messaging more generic:
Param ( [string]$Path = "D:\FTPSites\", [string]$SMTPServer = "smtpservername", [string]$From = "SFTPAlert@domain.com", [string]$To = "user@domain.com", [string]$Subject = "New File Uploaded to FTP Site" ) $SMTPMessage = @{ To = $To From = $From Subject = "$Subject at $Path" Smtpserver = $SMTPServer } $File = Get-ChildItem $Path | Where { $_.LastWriteTime -ge [datetime]::Now.AddMinutes(-10) } If ($File) { $SMTPBody = "`nThe following files have recently been added/changed:`n`n" $File | ForEach { $SMTPBody += "$($_.FullName)`n" } Send-MailMessage @SMTPMessage -Body $SMTPBody }
Rate this:
Share this:
Related
September 11, 2012 - Posted by Martin9700 | PowerShell | Get-ChildItem, scan for changed files, scan for new files, Send-MailMessage, splat, splatting
24 Comments »
Leave a Reply to Israel Anthony Lopez Cancel reply
Blog Search
Blogroll
Links
Categories
- General (22)
- Humor (1)
- MS SQL (3)
- PowerShell (78)
- Powershell – Best Practices (6)
- Powershell – Getting Started (9)
- PowerShell – HTML Reporting (6)
- Powershell – Performance (12)
- Random Thoughts (8)
- Technical (17)
Top Posts & Pages
Archives
- March 2021 (1)
- May 2019 (1)
- February 2019 (1)
- November 2016 (2)
- August 2016 (1)
- March 2016 (1)
- February 2016 (2)
- January 2016 (1)
- December 2015 (1)
- November 2015 (1)
- October 2015 (1)
- June 2015 (2)
- May 2015 (1)
- April 2015 (2)
- March 2015 (1)
- January 2015 (4)
- December 2014 (1)
- September 2014 (4)
- August 2014 (1)
- July 2014 (4)
- June 2014 (3)
- April 2014 (3)
- March 2014 (2)
- February 2014 (2)
- January 2014 (4)
- December 2013 (3)
- November 2013 (1)
- October 2013 (3)
- August 2013 (2)
- May 2013 (3)
- April 2013 (6)
- March 2013 (7)
- February 2013 (8)
- January 2013 (10)
- December 2012 (9)
- November 2012 (7)
- October 2012 (12)
- September 2012 (9)
- August 2012 (4)
- April 2011 (1)
- August 2010 (2)
- April 2010 (1)
- January 2010 (1)
- December 2009 (1)
- September 2009 (2)
- August 2009 (1)
- July 2009 (2)
Tag Cloud
ACL Active Directory Add-Member adsi Advanced Function alan rickman Background Jobs Best Practices ConvertTo-HTML Credentials csv Dfs dfs monitor dfs monitoring Discovery email employee directory Exchange Exchange Implicit Remoting Foreach ForEach-Object function Functions Get-ChildItem get-command get-help Get-Member GitHub Google Maps Google Visualizations Hashtable hbo html html report HTML Reports Import-SPWeb Invoke-SQLQuery Jobs JSON Meraki Modules monitoring mos def movie review Multi-thread multithread New User New User Automation object Pebble performance pipeline powergui PowerShell Powershell Get Started PowerShell Jobs PSObject Pushover regex Remoting Reporting RESTful ScriptProperty secure credentials Set-AlternatingRows Sharepoint spiceworks Spiceworld sql Strings Technical Veeam VMware WMI Write-Progress
Follow me on Twitter
My TweetsMe
Martin9700
Father, husband, IT Pro, scripter, blogger, cancer survivor. I tweet and blog about my IT passions, Powershell chief among them. Very active at Spiceworks.
Spiceworks
LinkedIn
RSS
-
Join 375 other subscribers
[…] Load up a hash table with all of static properties we’ll need for Send-MailMessage–another splat! […]
I am not very PS savvy but generally I know when something says Line-Char to diagnose a problem. I am getting “Missing Expression after unary operator ‘-‘ at Line:1 char:2” of this exact script that was created. I am using Notepad++ to write this out. I know this post is old but this is exactly what my company needs and no PS admin to do it. 🙂 Thank you.
Great script! I stopped coding years ago so rather than me beat my head on the wall, can you post a modification to the script that will allow for multiple directories to be searched with each notifying a different user?
For example USER A Path = “\\serverA\users\UserA\”
To = “usera@domain.com”
User B path = “\\serverA\users\UserB”
To = “userB@domain.com”
Is there a way to exclude a particular file type?
Sure. Line 16 is here the Get-ChildItem occurs, you should be able to use the -Exclude parameter to exclude the files you want. Might have to add a *.* at the end of $Path. Let me know what ends up working!
Would like to know if there’s a way to save to .txt (and appending to file) file instead of sending an email.
[…] Source: http://community.spiceworks.com/scripts/show/1595-scan-folder-for-changed-added-files Blog: https://thesurlyadmin.com/2012/09/11/scan-a-folder-for-changes/ #> Param ( [string]$Path = “D:FolderMonitor”, [string]$SMTPServer = […]
Pingback by PowerShell – Scanning Folder for New File | Chris Memo | April 12, 2015 |
I am looking into do something in reverse of this. When a file or specific set of files are not updated after a period of time I would like to get a notification. I am thinking about after 30 minutes or 1 hour the script would send out a notification via email to indicate a file has not been updated.
Do you find a wat to be notify when no fo=iles was updated?
hi,
i would like to use your script but i need a script who looked on a specified folder and when we add a new files , this will send a email to other person to inform her that a new file was added , can you help me with this??
thanks
That’s what this script already does. Are you having a problem with it?
no , it’s not working, i have a person who every wednesday , drop a file on a specified folder, i made a scheduled task and it’s not working , the script seems work only for 10 minutes changed…
This worked great! Thank you for posting this.
I was playing with this and found it very useful. Looks like the perfect tool to let users know there are new uploads on an FTP folder they need to monitor. Thank you. Is there a variable or command that would allow it to search and report on files and folders contained within sub-folders also?
Sure, just add a -Recurse to the Get-ChildItem cmdlet: $File = Get-ChildItem $Path -Recurse | Where …
Works great. One question, how to add the size of the files that have been added/changed?
Hi, How can I send to update to multiply recipients. when I try to add a second email in $to variable I get an error
Works awesome, I adopted it with gmail credentials and it works well so far. One problem I am having is the file path has spaces so we aren’t able to click the link from outlook. ex: \\FileServer1\Public\Inspection Dept\example1.txt Is there any way around this?
Fantastic!!!
Kudos on this script, it’s helped a ton – BUT… 🙂 I’m with a previous requester here (JDG) needing a solution for checking multiple paths for a new file. I’ve played around with parameters but not having any luck. Would you be able to offer some advice?
Either Get-Content for a list of paths.
or…
“\\server1\folder1”, “\\server2\folder2”, etc.
Thanks for the script. I can run the script from the command line and I get an email with the info. When I add it the task i do not get anything. Do you have any troubleshooting tips? Thanks
I got it to work. Thanks
[string]$recipients = “a@a.com,b@b.com,c@c.com”,
[string[]]$To = $recipients.Split(‘,’),
https://stackoverflow.com/questions/10241816/powershell-send-mailmessage-email-to-multiple-recipients
Hi there i have this script working but i would like to be able to have the file name listed in the email also.
currently it just sends the folder location/s