Date Tags From Filename

Summary: Tags a file based on the date in its filename.
Requires: EagleFiler
Install Location: ~/Library/Scripts/Applications/EagleFiler/
Last Modified: 2015-05-13

Description

This script adds month and year tags to the selected files based on the date in the filename. For example, a file named “ATT 02-15-12 bill” would be assigned the tags “feb” and “2012”.

Installation Instructions · Download in Compiled Format · Download in Text Format

Script

--my runTests()
my tagSelectedFiles()

on tagSelectedFiles()
    
set _addCompanyTag to false
    
set _replaceExistingTags to false
    
set _moveToCompanyFolder to false
    
tell application "EagleFiler"
        
set _records to selected records of browser window 1
        
repeat with _record in _records
            
set _filename to _record's filename
            
set _tagNames to my dateTagNamesFromFilename(_filename)
            
set _company to word 1 of _filename
            
if _addCompanyTag then copy _company to end of _tagNames
            
if not _replaceExistingTags then set _tagNames to (_tagNames & _record's assigned tag names)
            
set _record's assigned tag names to _tagNames
            
if _moveToCompanyFolder then my moveToFolderNamed(_record, _company)
        
end repeat
    
end tell
end tagSelectedFiles

on moveToFolderNamed(_record, _folderName)
    
tell application "EagleFiler"
        
set _library to _record's library document
        
set _root to _library's root folder
        
try
            
set _folder to library record _folderName of _root
        
on error
            
set _tempFolderPath to do shell script "mktemp -d -t 'NewFolder'"
            
tell _library to set {_folder} to import files {_tempFolderPath}
            
set _folder's filename to _folderName
        
end try
        
set _record's container to _folder
    
end tell
end moveToFolderNamed

on dateTagNamesFromFilename(_filename)
    
set _dateString to my dateStringFromFilename(_filename)
    
set _monthName to my lowercaseString(my formatDate(_dateString, "+%b"))
    
set _year to my formatDate(_dateString, "+%Y")
    
return {_monthName, _year}
end dateTagNamesFromFilename

on dateStringFromFilename(_filename)
    
set _regex to "(\\d\\d?[-:]){2}(\\d\\d){1,2}"
    
set _script to "python -c \"import sys, re; print re.search(r'" & _regex & "', sys.argv[1]).group(0)\" "
    
return do shell script _script & _filename's quoted form
end dateStringFromFilename

on lowercaseString(_string)
    
return do shell script "echo " & _string's quoted form & "| tr '[:upper:]' '[:lower:]'"
end lowercaseString

on formatDate(_dateString, _outputFormat)
    
set _formats to {"%m-%d-%Y", "%m:%d:%Y", "%m-%d-%y", "%m:%d:%y"}
    
repeat with _format in _formats
        
set _script to "date -j -f '" & _format & "' " & _dateString's quoted form & " " & _outputFormat's quoted form
        
try
            
return do shell script _script
        
end try
    
end repeat
    
error _dateString & " did not match any date formats."
    
return
end formatDate

on runTests()
    
my test("ATT 02-15-12 bill", {"feb", "2012"})
    
my test("ATT 2-15-2012 bill", {"feb", "2012"})
    
my test("ATT 04-02-09 bill.pdf", {"apr", "2009"})
    
my test("ATT 04-01-09 disconnect notice.pdf", {"apr", "2009"})
    
my test("DT 03-03-09.pdf", {"mar", "2009"})
    
my test("DT 03:03:09.pdf", {"mar", "2009"})
    
my test("DT 03-03-2009.pdf", {"mar", "2009"})
    
my test("DT 3-3-2009.pdf", {"mar", "2009"})
    
my test("DT 03:03:2009.pdf", {"mar", "2009"})
    
my test("DT 3:3:2009.pdf", {"mar", "2009"})
    
my test("Geico Est Body Work 6:20:13.pdf", {"jun", "2013"})
end runTests

on test(_filename, _tagNames)
    
my assertEqual(my dateTagNamesFromFilename(_filename), _tagNames, _filename)
end test

on assertEqual(_actual, _expected, _name)
    
if not my isEqual(_actual, _expected) then
        
set _title to "Test Failed: " & _name
        
set _message to "Expected “" & _expected & "” but got “" & _actual & "“."
        
display alert _title message _message
    
end if
end assertEqual

on isEqual(_a, _b)
    
considering case
        
set AppleScript's text item delimiters to "|"
        
return _a is equal to _b -- Converts to strings
    
end considering
end isEqual