Wednesday, January 29, 2014

Bulk Update File Time Stamp Based On Name

So there are a ton of bulk file updaters out there, including ones that shift or set timestamps (my favorite being this one from NirSoft). There are even a couple that update based on EXIF data. But what I wasn't able to find was one that updated based on the file name. Okay, I found one but it required Cygwin and I wasn't that ambitious.

I've been doing a lot of data mining using PowerShell recently, so I've really come to appreciate how powerful it is. I'm amazed at what I can do with such a simple scripting language and I know what I'm doing pales in comparison to what "real" developers can do with it. But it's fun for me so I wrote a little script to update the Creation Time and the Modified Time on the files based on the *name* of the file.

About a month ago I moved about a thousand pictures from my phone's internal storage to the SD card to free up some space. Whatever utility I used wasn't smart enough to copy the time stamps to the new file, so suddenly I had a couple of years worth of photos all with the same date. Needless to say this made browsing the gallery on the phone and actually finding something a pain.

So anyway, here's the script. I'm sure it's not that elegant and I know I can condense a lot of this, but I wanted it to be easy to understand and modify as well. If it helps you say thanks in the comments.

(It's hard to colorize this in blogger and keep the formatting good, so sorry about that.  You can download the actual script from here.)


<# This script updates the created timestamp and the last modified timestamp of all of the files in a folder based on the filename being in the following format: YYYYMMDD_HHMMSS.jpg (doesn't have to be jpg) It only matters that the first 15 characters are in that format - anything afterwards is fine. It assumes that you are in the folder you wish to process before you call the script. There's no error checking in this except to check for an empty folder, so don't use this if you don't know what you're doing. I spent about 10 minutes writing and testing this script and it served its purpose for me. It should be very easy to modify for different file name formats. *** MAKE A BACKUP BEFORE YOU RUN THIS *** THE SCRIPT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SCRIPT OR THE USE OR OTHER DEALINGS IN THE SCRIPT. #> $FilesInFolder = Get-ChildItem $NumFiles = $FilesInFolder | Measure-Object if ($NumFiles.Count -eq 0) { Write-Host "No Files Found" Exit } foreach ($FileInFolder in $FilesInFolder) { #Yes, this could be condensed but I don't like extremely long lines in my ISE. #(or breaking lines if I don't have to) $YearCode = $FileInFolder.Name.Substring(0,4) $MonthCode = $FileInFolder.Name.Substring(4,2) $DayCode = $FileInFolder.Name.Substring(6,2) $HourCode = $FileInFolder.Name.Substring(9,2) $MinuteCode = $FileInFolder.Name.Substring(11,2) $SecondCode = $FileInFolder.Name.Substring(13,2) [datetime]$FileDate = "$YearCode`-$MonthCode`-$DayCode $HourCode`:$MinuteCode`:$SecondCode" write-host "$FileInFolder - $FileDate" $FileInFolder.CreationTime = $FileDate $FileInFolder.LastWriteTime = $FileDate } write-host "" write-host "Done..."