Find files by month ignoring the year, with AppleScript

I find that I take a lot of pictures of seasonal stuff, and  I wondered how to find images taken at the same time of year but in different years.  As it turns out, there’s no obvious way to do that.  Computers keep time by counting the number of ticks or seconds since an arbitrary start date, and calculate a particular date and time  from the number of ticks.  So most date functions treat time in its relation to the arbitrary start date.  Mac OSX gives the current date as “Saturday, June 8, 2013 9:33:35 AM”, but when you search by date from iPhoto or Aperture,

Date search in Aperture

Date search in Aperture

you can only search for time periods relative to a given time.  It might be handy to add a “contains” to the list, eg, “Date contains May”, but alas.

Nevertheless,  AppleScript can easily parse a file’s creation date to let us search for files by “month of creation date”,  which might return “June” or a day of the week with “weekday of creation date”, which might return “Saturday”.

Here’s a simple script which has you choose a folder, then uses the Finder’s label index property to label all files with “May” in their creation date.  The script will find all files in the folder made in the chosen month, label them with one of 8 indices (0 thru 7; 0 is no label).  It sorts the finder window by label, so all your labels are grouped; then it selects the labeled files.  From the Finder, you can run QuickLook by touching your  spacebar.  You can then browse all the files from May no matter what year.  We’re hard-coding the label index (5) and month (May) for now.

set the_folder to choose folder with prompt "Select a folder:"
set the_label_index to 5
--label index:
-- 0=none
-- 1=orange
-- 2=red
-- 3=yellow
-- 4=blue
-- 5=purple
-- 6=green
-- 7-grey

tell application "Finder"
    activate
    set the_files to every file of the_folder
    repeat with current_file in the_files
        set the_creation_date to creation date of current_file
        set the_month to month of the_creation_date
        --we're hard coding the month now but will assign a variable in the next version
        if the_month is May then
            set the label index of current_file to the_label_index
        end if
    end repeat
    sort the_folder by label index
    select (every document file of the_folder whose label index is the_label_index)
end tell

It would make it easier for the user to select the month from a list, especially since month names vary by OSX language preferences.  Also, who knows what label index goes with what color?  We can use AppleScript’s choose from list method  to make those selections easier:

set the_month to choose from list {January, February, March, April, May, June, July, August, September, October, November, December} with prompt "Choose a month"
if the_month is false then error -128 --handles cancel button
--the chosen month is an item of a list, so we need to get it from the list
set chosen_month to item 1 of the_month

set the_label to choose from list {0, 1, 2, 3, 4, 5, 6, 7} with prompt "Choose a label; 0 is none, 1 orange, 2 red, 3 yellow, 4 blue, 5 purple, 6 nauseous green, 7 grey"
if the_label is false then error -128 --handles cancel button
set the_label_index to item 1 of the_label

Also, you may want to have the script navigate folders recursively.  For that, we turn the script into a subroutine.  The script calls the subroutine, then call it again for each sub-folder.   Here’s a script that does that:

--Label files by month
--recursively gets month of creation date and sets label for chosen month
--jjmcclintock 20130606

set the_folder to (choose folder)
set the_month to choose from list {January, February, March, April, May, June, July, August, September, October, November, December} with prompt "Choose a month"
--need to handle error if user cancels
if the_month is false then error -128
--the chosen month is an item of a list, so we need to get it from the list
set chosen_month to item 1 of the_month
--it would be nice to call the labels by color name and let the script convert your choice to index numbers, but
--putting that in the prompt is as far as I'm likely to go with it.
set the_label to choose from list {0, 1, 2, 3, 4, 5, 6, 7} with prompt "Choose a label; 0 is none, 1 orange, 2 red, 3 yellow, 4 blue, 5 purple, 6 nauseous green, 7 grey"
if the_label is false then error -128
set the_label_index to item 1 of the_label

--call the subroutine, passing the chosen parameters
label_for_month(the_folder, chosen_month, the_label_index)

--the subroutine:
on label_for_month(the_folder, chosen_month, the_label_index)
    tell application "Finder"
        --Check each of the  files in this folder
        set the_files to every file of the_folder
        repeat with current_file in the_files
            set the_creation_date to creation date of current_file
            set the_month to month of the_creation_date
            if the_month is chosen_month then
                set the label index of current_file to the_label_index
            end if
        end repeat
        sort the_files by label index
        --now each sub-folder
        set sub_folders_list to folders of the_folder
        repeat with the_sub_folder_ref in sub_folders_list
            my label_for_month(the_sub_folder_ref, chosen_month, the_label_index)
        end repeat
        sort the_files by label index
    end tell
end label_for_month

The script sorts the files by label, so you should see big blocks of similarly colored file labels. The script can’t select files across folders, but you can select them manually and run QuickLook (spacebar).  While the script is non-destructive, you may want to use it with care with folders that have many sub-folders; it can take a long time to run.  If you use labels for other purposes, this will! make a mess.

It should be fairly easy to modify this script to move or copy selected files if you want them for, for example, a calendar project. The choose from list method also supports multiple selections (“multiple selections allowed“) but you would have to futz with the the_label_index variable to make it work right.  It seems like overkill. But  for getting Saturday ball game snapshots from years past, or April invoices, or Christmas movies, this should do the trick.

Control System Prefs with AppleScript

I use TeamViewer to control the PC in the Hut, because it’s free, and it often works quite well.  The thing that drives me most nuts about it is how to right-click remotely.  I’m working from a Mac Book Pro with a trackpad.  I suppose I could actually use a two button mouse, but I haven’t used a mouse with a MBP forever.  I’m not even sure I have a two-button mouse… The solution is to go to the System Prefs Trackpad panel and set the Secondary Click checkbox for two-finger click.  trackpad-panel

That actually works great for TeamViewer remote sessions.  But it drives me nuts in MacLand, because I seem to use two hands on the trackpad and am constantly getting unwanted context menus.  So I wanted a handy way to turn on or off the two finger click trick programatically, which is to say, with AppleScript.

So how do you get your hooks into the Systems Preferences elements?

The key is to use System Events to get and set the window’s UI elements.  Here’s a simple script that collects the UI elements for the frontmost window of the application you want to peek at, in this case System Preferences:

tell application "System Preferences"
    --bring System Prefs to front
    activate
end tell

tell application "System Events"
    tell process "System Preferences"
        set windowsProperties to entire contents of front window
    end tell
end tell

return windowsProperties

The results window displays a lengthy list of elements that you’ll have to noodle over to figure out what you want.  In this case, I had opened System Preferences and clicked  to open the Trackpad panel, as in the image at top.  Here’s what the ScriptDebugger window looked like:  results of ui inspector

 

Here’s the pasted value (pasted into ScriptDebugger) from the results for “checkbox 2 of tab group 1 of window “Trackpad” of application process “System Preferences”:

tell application "System Events.app"
    tell application process "System Preferences"
        tell window "Trackpad"
            tell tab group 1
                tell checkbox 2
                    -- your code goes here
                end tell
            end tell
        end tell
    end tell
end tell

This nested tell set is clunky, but lets you easily understand exactly what’s going on, and you can just paste it into a script to get or set a value to a particular UI element.  I had to horse around to check or un-check the  secondary click checkbox.  “Normal” checkboxes have a value of “0” for unchecked and “1” for checked.  The script would let me get the value, “0” or “1”, but not let me set the value.  However, it did let me treat the checkbox like a button, and “click” it.  Go figure. That would be a problem if I really needed to set a particular value, but in this case, I’m happy to let it toggle:

--toggles "2 finger click" for secondary click on or off via trackpad pane of system Prefs
--needs "does trackpad panel exist?" 
--JJ McClintock 20130411

tell application "System Preferences"
    activate
end tell
tell application "System Events"
    tell application process "System Preferences"
        tell window "System Preferences"
            tell scroll area 1
                --hopefully this will catch issues if no trackpad panel exists
                try
                    click button "Trackpad"
                    tell application "System Events"
                        tell application process "System Preferences"
                            tell window "Trackpad"
                                tell tab group 1
                                    ----set value doesn't seem to work
                                    --set value of checkbox 2 to 1
                                    ----get works fine
                                    --get value of checkbox 2
                                    --click works as toggle
                                    click checkbox 2
                                end tell
                            end tell
                        end tell
                    end tell
                end try
            end tell
        end tell
    end tell
end tell
--we want to quit System Prefs when we're done
tell application "System Preferences"
    quit
end tell

I saved the “toggle 2 finger secondary click” script as an application bundle and placed it in my script menu folder. Now I can turn on 2 finger click when I begin a TeamViewer session and turn it off the same way when I’m done.

Use AppleScript to Manage PDFs

 

I often collect PDFs off the web, and save far too many of them.  But often they are tear sheets, product blurbs, or rocket science I don’t understand that I don’t want to have cluttering up the hard drive.  When I have finished with a PDF that I want to trash,  I use an AppleScript to immediately delete the file without leaving Acrobat.  The script is accessed from the Script menu in the Menu Bar, and immediately deletes the file.  The document is still open, but when you close it, it’s gone.

Here’s a simple script that may be useful  It works with Acrobat Pro and Acrobat X, but will not work with Acrobat Reader, because Reader is not “scriptable”.  It also can’t work with Preview, which is also not scriptable (!)

--this script will immediately delete the active Acrobat document
--these "--" things are comments
--use at your own risk, etc
--attribute to JJ McClintock 20121101

--initialize variable
set doc_path to ""

tell application "Adobe Acrobat Pro"

	activate
	--get the name & path of the active document
	set doc_path to get file alias of active doc as string
end tell
--a dialog confirms
display dialog "Are you sure you want to delete " & doc_path & " ?"
tell application "Finder"
	move file doc_path to trash
end tell

tell application "Adobe Acrobat Pro"

	activate
end tell

That’s the end of the script, not much to it.  It asks Acrobat what and where the file is, and then tells the Finder to trash it.

How to make it work?  Copy the script. Locate the AppleScript editor on your Mac – it’s in your Utilities folder, but it’s easiest to use Spotlight, CMD-Spacebar and type applescript editor.  Open the editor and paste the script.    Click the “Complile” button, which will format and check the script to make sure it doesn’t violate any obvious rules.  Save the file: select “Application”  in the “File Format” dropdown, name the file “Delete PDF” or whatever, and save it in a convenient location.  It’s going to wind up in your script menu, but the actual folder for your script menu is buried in the bowels of your home directory.  Here’s how to find it.

While in the editor, select Preferences from the AppleScript Editor menu and check the “Show Script menu in menu bar” box. Close the prefs window, you should see a scroll icon in the right part of the menu bar.

what the script menu looks like

Click the Script icon and you will see a bunch of Apple supplied scripts, I think, but at the top select “Open Scripts Folder|Open User Scripts Folder.  That’s a short way of getting to the scripts folder, which is located in Mac HD: Users:Your User name:Library:Scripts,  Since Apple has invisibilized the Library folder, you have to horse around to get to it.  Alternatively, from the Finder, select the Go menu while holding the Option key, and select Library.  Anyway if you place your new Delete PDF script in the user scripts folder, it’s available at all times from the scripts folder in the menu.

Hopefully you will find this to be a handy little gadget.  If you have several documents open, the script will delete the “front most” one. If you make a mistake, your file is still open and can be re-saved, and is in the Trash and can be recovered.

I have another handy script I use frequently to rename PDF documents.  How often do you collect a PDF with the helpful name “aa3695-05.pdf”?  If I want to keep it for reference I’d like to rename it something I can live with, like “Lucky Imaging-Hi Rez Imaging from the Ground.pdf”   Using the handy “Rename PDF” script, it’s easy.

--saves pdf with new name, deletes original pdf
--default save folder is Documents
--won't work if file doesn't exist on disk.  Why should it?
--won't work on secure documents. They wouldn't be secure.
--modified 20110526 to (awkwardly) handle long file names
--since acrobat's applescript implementation doesn't permit file names longer than 32 char,
--need to make temporary short file name for saving, which will be renamed with the chosen long file name
--cleaned up 20121101

--initialize some variables
set default_folder to (path to documents folder from user domain as string)
set doc_path to default_folder
set new_file to choose file name with prompt "Enter new file name" default location alias default_folder
set short_name to default_folder & "short_name.pdf"
set file_string to new_file as string
set text item delimiters to ":"
set file_string_list to every text item of file_string
set last_word to text item -1 of file_string

tell application "Adobe Acrobat Pro"
	set doc_path to get file alias of active doc as string
	set active_doc to name of active doc
	--try blocks help the script to fail gracefully if an error occurs
	try
		save active doc to file short_name with replacing
		--save active doc to file short_file with replacing
	on error
		--biggest source of error is trying to rename a secured document
		display dialog "Save failed.  Is the document secured?  You can still rename using Save As or in the Finder." buttons {"Cancel"}
	end try
	close active doc
end tell

set path_string to quoted form of POSIX path of short_name
set shell_string to "cp " & path_string & " " & quoted form of POSIX path of new_file & ""
--shell script uses unix commands to do file tasks, in this case copy
do shell script shell_string
tell application "Adobe Acrobat Pro"
	open file new_file
end tell

tell application "Finder"
	--trash original file and the temporary "short_name" file
	move file doc_path to trash
	move file short_name to trash
end tell

--restore text item delimiters to default setting
set text item delimiters to ""

Prepare this script like you did the “Delete PDF” script before.  From Acrobat Pro or Acrobat X, if you want to rename a PDF file to something human readable, go to the script menu, select the “Rename PDF” script.  You’ll be prompted for a name and location for the file.  If for some reason Acrobat won’t let you rename the document, for example, it is secured, then you get an alert.  You should still be able to go to the Finder, and rename it the way you used to.

GOES 13 looks at Hurricane Sandy

After being down for maintenance since Sept 17,  GOES 13 is back in service.  Which is good because my AppleScript more or less broke while it was down.  “The trouble stemmed from a motor vibration, which caused a lubricant buildup that obstructed the spinning motion of the filter wheel in the sounder. A team of engineers from NOAA, Boeing and ITT suppressed the vibration, the filter wheel restarted and is running smoothly, with improved performance. ” (http://www.nesdis.noaa.gov/)

Here’s today’s view of Hurricane Sandy, which is just now clobbering the East coast. It’s from the Visualization Lab, and has a floating URL that will be something else tomorrow.

Here’s the output of the AppleScript:

GOES 13 on standby, GOES 14 activated

I use an AppleScript to scrape files from the GOES archives at http://goes.gsfc.nasa.gov/goeseast/fulldisk/ir4/ The collected files are then processed a bit in Photoshop, named with sequence numbers and fed to QuickTime Player 7 as an image sequence to make a QuickTime movie.  Today, the script broke, and upon investigation, I found that the GOES 13 satellite is unavailable and that 14 had been activated for US East coast coverage.  That will create a hop in the movie. Here’s the difference in coverage:

Consecutive images (with about a 21 hr gap) from 13 on the left and 14 on the right showing difference in coverage.

 

Here’s the YouTube movie, glunks and all:

GOES ECIR Satellite of Hurricane Isaac Development

Using an AppleScript, the individual images were collected from NOAA’s archive site, and made into a movie with QuickTime Player 7.  The coverage is from 8/05/2012 to 09/05/2012, showing the development of Hurricane Isaac.  The images are from the IR (infra-red) band of the GOES, which permits 24 hour coverage.