Photos, screenshots, audio recordings … there are countless files that are stored (or should be stored) with the event’s date in the name. And, as it becomes easier to create these, they accumulate at an ever-increasing rate… usually in one folder without any type of organization. Of course, we could take the time to organize those folders, move files into proper folders, and delete what we don’t … oh, nevermind. Who am I kidding? Nobody does that.
For me, one simple step to greatly improve the value of these files is to organize them by their event date. This would at least help me find them if I need them. Grouping all files from the same day would help narrow down what may be relevant to that specific time frame. Sadly, there is no magical command, or even a utility, that will do this easily. And, even if one exists, it surely won’t work on all of the machines I use.
Well, now there is! Enter File Date Organizer and Ugly Date!
Of course, I chose to write these two utilities using NodeJS to ensure I can use them on macOS, Windows, and Linux. That’s a no-brainer.
Writing File Date Organizer came to a screeching halt the moment I pulled in the first few files and noticed that every utility I use to create screenshots formats the file names with a completely different convention…
Screen Shot 2016-07-29 at 6.11.png
Screenshot 2014-09-07 13.36.45.png
Snapshot-3208-2016-10-11-08-31-16.JPG
Even worse was the error I received when I tried to use MomentJS (the de facto utility for untangling these odd formats) to untangle those formats…
Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info. After doing a bit of research, and seeing what options exist out there for detecting date formats, I understood why MomentJS decided to pull out their detection logic. Virtually every plugin or library out there uses basic RegEx (at best) to find four-digit years, two-digit minutes, or similar and fails miserably. They seem to all want so badly to return a value that they make assumptions along the way. In the end, most of them return bad values instead of no values at all… which, in my opinion, is the worst possible scenario. This is where Ugly Date comes into play.
Ugly Date is a bit of an experiment and takes a slightly different approach to parsing. Instead of simply using a series of RegEx patterns, Ugly Date contains groups of patterns and validators with the intent on locating possible matches, within the value, and then scores and compares those results with each other to return the best pattern versus returning any qualifying pattern. The change feels like a bit of a tradeoff. In the beginning, it will mean more maintenance and adding of patterns. However, over time, it should mean a better result when detecting more diverse patterns. Basically, you supply a string and Ugly Date parses it and returns both the date as well as a slew of potentially helpful information:
{
"date": "2015-07-09T17:33:25.000Z",
"hasDate": true,
"hasDay": false,
"hasTime": true,
"pattern": "Screen Shot YYYY-MM-DD at hh.mm.ss a",
"value": "Screen Shot 2015-07-09 at 1.33.25 PM",
"values": {
"YYYY": 2015,
"MM": 7,
"DD": 9,
"h": 1,
"mm": 33,
"ss": 25,
"aa": "PM"
},
"locations": [
{
"formal": "YYYY-MM-DD",
"pattern": "YYYY-MM-DD",
"position": 12,
"type": "DATE",
"value": "2015-07-09",
"values": {
"YYYY": 2015,
"MM": 7,
"DD": 9
}
},
{
"formal": "hh.mm.ss a",
"pattern": "h:mm:ss aa",
"position": 26,
"type": "TIME",
"value": "1.33.25 PM",
"values": {
"h": 1,
"mm": 33,
"ss": 25,
"aa": "PM"
}
}
]
}
Unlike its sister, File Date Organizer is far simpler than Ugly Date. There’s really nothing magical happening under the hood. You supply the source & target folders, tell it if you want to move or copy, overwrite or ignore, and let it go. In turn, it uses the logic within Ugly Date to parse each file and move them into a folder structure with a property date hierarchy:
The command itself is fairly logical with many “either / or” type of choices. Other than the source and target folder paths, the rest is somewhat a la carte. The basic command…
file-date-organizer \
--source "/Users/flackey/Documents/Screenshots" \
--target "/Volumes/MPHD01/Screenshots" \
--use-name \
--move
…can be swapped out with several other options. For example…
--move
or --copy
--ignore
or --overwrite
--use-created
or --use-modified
(for filenames not having a date)
It will also build your target folder structure using almost any of the date sections by using various --add
switches. For example, adding --add-second
causes the entire folder structure to be built all the way down to the seconds in the date value (ie, /YYYY/MM/dd/HH/mm/ss
). There is a full list of switches on the project page. And, of course, the library can be used programmatically by pulling it into a Node project.
Granted, none of this is a perfect solution. And, Ugly Date is taking a very different approach to parsing dates compared to more traditional libraries. If nothing else, this satisfied the anal-retentive side of my brain.