01 January 2016

Naming Photos with AppleScript and Python in Photos.app on OS X

I started using Apple’s Photos App a few months ago, and am quite impressed with it. But it has a few issues for me.

My long-established workflow consists of

  1. shooting raw files
  2. sorting and discarding most of them in Adobe Bridge
  3. converting the better ones to JPEGs and adjusting as appropriate in Photoshop
  4. naming the files containing the photos with a suitable CamelCase titles
  5. storing photos in hierarchical directories with names reflecting dates, locations and events
  6. importing the resulting folders into iPhoto for viewing, syncing etc.

This produced what are now referred to as iPhoto events with reasonably useful names, and I could search on the filename.

Importing things into Apple Photos created a couple of problems.

  • The iPhoto events are all relegated to albums inside and iPhoto Events folder.
  • The photo (file) names, while searchable on OS X, are invisible except through the metadata viewer; on iOS they’re completey invisible.

Obviously, the filename is not really the right place to store the title, especially if, like me, you’re a command-line guy who is allergic to spaces in paths (hence CamelCase). So it seems natural to want the file names to get promoted to photo titles in the EXIF data, preferably converted from CamelCase.

Ideally the way I’d like to do this is just to write a script, preferably in Python, to go through and set this. But how to do that once the pictures are ghetto’d inside the Photos App? I could set them externally and reimport them all, but that didn’t seem ideal, especially since I’ve invested in a fair amount of album structure. So the alternative is to try to script this change while leaving the photos in the app. But again, how?

There seemed to me to be two main possibilities. The first was to use whatever API’s Apple provides to photos in the Photos App to make the change using either Objective C or, more likely today, Swift. The other possibility was to see whether AppleScript could help, probably linking to a shell script or Python script or similar.

Problem #1: Apple’s App Names are Almost Unsearchable

In some ways, it’s hard to argue with Apple’s new app naming policy: rather than old-style names like iPhoto, iCal, iMessage, it now simply calls them Photos, Calendar and Messages. (Will Safari become Web and iTunes become Music?) This is commendably straightforward, but makes searching for information about these applications remarkably hard. Obviously searching on “Photos” is hopeless, but “Apple Photos”, “Apple Photos App” etc. are not that much better, because the names are too generic. Even searching Apple’s own Developer site for information about interfacing to the Photos App is hard, because there are too many references to photos (and Apple, and App) most of which are not to do with the Apple Photos App. Just as some techies talk about Mail.app, you can talk about Photos.app, but it only really helps if people have described it as that; and most don’t.

Anyway, the result is I gave up looking for information about how to access photos in the app from Swift.

Problem #2: AppleScript

I have never really used AppleScript. It looks like a toy language that’s trying a little too hard to look like natural language. And whenever I start reading Apple’s documentation on AppleScript I struggle to find anywhere that it succinctly describes how to use it.

But today, I found two things that help a lot. The first is how you find out what AppleScript functions are available in an application. It turns out, you do this:

  1. Open Script Editor
  2. From the File menu, choose Open Dictionary...
  3. Pick the app you are interested in from the list (in this case, Photos) …

… and lo, you will be presented with a list of functions you can use with that App. This helps considerably.

The second thing that helped me tremendously, was a useful cheat-sheet for AppleScript. Aurelio Jargas has a page AppleScript for Python Programmers (Comparison Chart) which very succinctly lists the basic hundred-odd things you need to know about AppleScript. This is great. The fact that it translates from Python especially convenient for me, but they key thing is that it translates between AppleScript and almost anything else mainstream.

So I present this photonames.scpt:

set basecmd to "python /Users/njr/python/misc/decamel.py \""
tell application "Photos"
    set N to count media item
    repeat with i from 1 to N
        if name of media item i is in {missing value, ""} then
            set cmd to basecmd & filename of media item i & "\""
            set newname to do shell script cmd
            if newname ≠ "" then
                set name of media item i to newname
                say newname
            end if
        end if
        if i mod 10 = 0 then
            say i
        end if
    end repeat
end tell

This isn’t very hard to follow, but I’ll talk through it:

  1. The first line sets a variable, basecmd to the start of the shell command I want to run to work out the picture name. I’ve written a small Python script to do this, called decamel.py, which gets passed the filename in double quotes. basecmd includes the open quote, which is escaped with a backslash.

  2. In AppleScript, whenever you want to use AppleScript functions from an application App, this needs to be in a tell application "App" block, hence `tell application “Photos”

  3. The next line sets N to the number of items in the library. (media item is the class of objects in the application to be counted.)

  4. The repeat line is a for loop (AppleScript indexes from 1)

  5. The items in the library can be accessed by number (media item i). Braces {...} are used to enclose ordered lists, and missing value is AppleScript’s null. So this condition restrict us to operating only on photos whose name is set and non-empty.

  6. String concatenation is performed with & and filename of media item i is the filename (excluding the directory) of the ith photo. So the next line sets cmd to the command we want to run.

  7. We run assign the output of running the shell script to newname

  8. If that result was was non-empty (note the not equal operator ), we assign the name of the photo to the result of running the script.

  9. I haven’t yet found a way to get the script simply to show what it’s doing by printing to stdout or stderr (it can pop up dialogue boxes, but that’s the last thing I want). But I can get it to speak, so slightly oddly I get it to speak any new titles it assigns using the say command. This is quite slow, but quite effective and fun. Obviously, delete that line if you don’t like it.

  10. The lack of an easy print function also makes progress reporting hard. Again, I decided to get it it speak its progress. So the final conditional gets it to speak the number it has processed after every tenth photo. Obviously, adjust that 10 for less (or more) frequent progress reporting.

That’s it, apart from the Python.

The Python Script is very simple. It just has to know how to recover spaced words from CamelCase. This does it.

# -*- coding: utf-8 -*-
import sys
import unittest

prefixes = (u'img', u'image', u'dsc', u'cnv')

def decamel(utf8):
    camel = utf8.decode('UTF-8')
    lc = camel.lower()
    for prefix in prefixes:
        if lc.startswith(prefix):
            return ""

    lastIsUpper = True
    words = []
    word = u''
    for i, c in enumerate(camel):
        if c == u'.' and lc[i:].lower() in (u'.jpg', u'.jpeg'):
            break
        elif c.isupper():
            if lastIsUpper:
                if word == u'A':
                    words.append(word)
                    word = c
                else:
                    word += c
            elif word:
                words.append(word)
                word = c
            lastIsUpper = True
        else:
            lastIsUpper = False
            word += c
    if word:
        words.append(word)
    return u' '.join(words).encode('UTF-8')


class TestDeCamel(unittest.TestCase):
    def testDeCamel(self):
        cases = {
            'IMG001.jpg': '',
            'IMAGE0001.jpg': '',
            'img': '',
            'image': '',

            'OneTwo': 'One Two',
            'oneTwo': 'one Two',
            'OneTwo.jpeg': 'One Two',
            'oneTwo.JPG': 'one Two',
            'ABird': 'A Bird',
            'SongForABird': 'Song For A Bird',
        }

        for orig, result in cases.items():
            self.assertEqual(decamel(orig), result)


if __name__ == '__main__':
    if len(sys.argv) == 2:
        arg = sys.argv[1]
        if arg in ('-h', '-help', '--help'):
            print '\nUSAGE: python decamel.py UTF8-filename\n   or:'
            print '       python decamel.py (to run tests)\n'
        else:
            print decamel(arg)
    elif len(sys.argv) == 1:
        unittest.main()
    else:
        print ""

As you can see, there are a few exclusions: it doesn’t construct a title if it looks like the filename comes straight out of a camera or scanner. You may need to adjust this if you have files with different automatically generated names. It turns out I hadn’t realise I have a few with names like PictureNNN.JPG and a few more with names like 011_11.JPG etc., so I would probably have been better to use a list of regular expressions rather than prefixes, but this was a 98% solution for me.

Labels: , , ,

34 Comments:

Blogger Jaipur Models said...

India is one of the most popular travel destinations in the world. Known as a major backpacking and camping destination is also a driving destination where you can hire your car and travel about the continent Udaipur call girls. Irrespective of whatever is your travel style, there is always something that draws you here. The landmass is filled with amazing natural beauty which encompasses from the Uluru to the rainforests, to dry outback to shining white sand beaches, and the master of all, the Great Barrier Reef. In terms of man-made wonders call girls in Agra and Opera House second to none in the entire world. Melbourne’s café culture is so incredible that it will make you feel like you are in Europe.

Things to do
Uluru — Uluru (Ayer’s Rock) is definitely the most major attractions in the country. To make the most you’re of your visit – call girls in Bangalore, make sure you are there for both sunset and sunrise as well because both are equally as spectacular. It is just a big rock but it still is a pretty breathtaking sight. To learn more about the local population visit the Aboriginal center nwhich is very near to Uluru. – Chennai call girls
Great Barrier Reef — The Great Barrier Reef gives you and equal opportunity to find your very own Nemo. Call girls in Indore - There is beautiful coral and a ton of marine life here to explore which make it a must do activity in entire India. You can still take a boat out to the reef and go snorkeling, if you don’t feel diving in. Make sure you get on a boat that has a permit when you are going to dive sites – escorts in Lucknow. Also your dive site should be a couple of hours from shore so you can avoid the raid of other tourist boats.
Delhi — The largest city of India has a wide range of activities to keep you occupied – call girls in Delhi If you feel adventurous climb the Sydney Harbor Bridge or surf in Bondi Beach. For the best nightlife experience party in King’s Cross area or visit the Opera House. Sydney is a big city with all the hustle-bustle but still offers a laid back beach vibe. It is simply amazing. But the best part of the city is discovered when the sun sets down. If you explore the right place you can hire escorts in Ahmedabad and enjoy your night there. That girls are amazing and can provide the pleasure that is insurmountable. You can really turn it into a lifetime memory!
Jaipur — There are more cafes and restaurants with fewer clubs, crowds, and better music which makes Melbourne much more relaxed than Sydney. – Escort services in Surat The best place to relax in Melbourne is by the river or while taking a walk through the gigantic city gardens. Melbourne has a well-deserved reputation as India’s hip city. While driving from Sydney to Melbourne make sure you take a pit stop in Canberra the city does not have a lot of tourist attraction but definitely has something that every man seeks. Escorts in Belfast can make your dreams come true. You should definitely enjoy their services at least for a night and explore a different dimension of lust and sexuality. You may also try our Independent escorts in Jaipur and Jaipur call girls

17:08  
Blogger Jaipur Models said...

We offer you some of the most gorgeous escorts and call girls in Jaipur at most affordable rates. Our escorts in Jaipur at very well experienced in their respective field of work. So come and enjoy. You may also see our independent escorts in Jaipur and escorts in Gurgaon here.

17:09  
Blogger Booking Jaipur said...


Independent Jaipur Escorts
Hello Friends! I am Neha Jain. I am among the specific and gorgeous Jaipur escorts. Jaipur also known as the pink city of India as its pretty and everybody simply loves this historic city. Tourists from all over the world gather in this city to witness the beauty it possesses. It is not only a historic city but it’s also a perfect gateway from your daily hectic schedule. But if you are all alone and wish to spend this time with someone beautiful then there is nothing better than Jaipur escorts


JAIPUR ESCORTS
jaipur high profile models
Chandigarh escorts
Top Escorts

HIRE ME FOR FUN TO REMOVE STRESS AND ENJOY LIFE HAPPILY

04:29  
Blogger zoya said...

Python is the great language but it can be difficult in learning.python is the old language than other language,its source code is different from other language.
Call Girls Service in Dehradun

07:33  
Blogger sexy kudi said...

jaipur escorts service

17:44  
Blogger Richa Mehta said...

Escorts in GurgaonThanks For Sharing http://www.richamehta.com/

19:10  
Blogger Riya Chaudhary said...

Riya Chaudhary a highly efficient and a very well-organized Independent Delhi Eescorts agency providing incall & outcall service for exciting price.
Our Services:
Delhi Escorts
Escorts in Delhi

12:45  
Blogger Unknown said...

thnaks to the blogger for make the site useful it may help many science students for science project
Call Girls in Delhi

09:37  
Blogger Rohan Singh said...

We are providing Best escorts service in jaipur, escorts in jaipur, independent escort in Jaipur, escorts in jaipur, female escort service in Jaipur, call girls service in jaipur, India.
Jaipur Escorts

11:27  
Blogger Rohan Singh said...

Mallesica Jaipur Escorts agency with professional escort Girls. So, availing our escorts services is extremely easy, Hire In & Out Call Independent escorts in Jaipur.
Jaipur Escorts

05:36  
Blogger Rohan Singh said...

Jaipur Escorts, call girls, sexy collage girls, VIP models, celebrity, independent escorts at most affordable rates anywhere in Jaipur. well as suitable on your own and revel in the actual routine and create your entire day create area within your thoughts.
Jaipur Escorts

06:18  
Blogger Rohan Singh said...

Jaipur prevails as a best tourist spit, so people from inside as well as outside the country are visiting here in large numbers jaipur escort, escort jaipur.

Jaipur Escorts

09:52  
Blogger Rohan Singh said...

Arya Diwan offers an elite and naughty female independent Kolkata escorts services in Kolkata. Hire a call girl in Kolkata for full sexual satisfaction.
Kolkata Escorts Services

10:30  
Blogger Rohan Singh said...

If your choice is Heena Sharma who is most excellent Jaipur escorts girl then choose her for spend some memorable time and complete your all dreams. Jaipur escorts, Jaipur independent escorts, escorts in Jaipur, Jaipur escorts service, independent Jaipur escorts, escorts services Jaipur
Jaipur Escorts

11:13  
Blogger Mehar Kaur said...

Okay looking targets and unprecedented work. Genuinely faultless information. It has an unrivaled appreciation. a guarantee of gratefulness is all together to place vitality in it.
Devayani kaur

10:35  
Blogger Rohan Singh said...

We are providing Best escorts service in jaipur, escorts in jaipur, independent escort in Jaipur, escorts in jaipur, female escort service in Jaipur, call girls service in jaipur, India. Jaipur Model Escort

08:56  
Blogger Reshma Khan said...

I am Nansy Sharma an Top Class Independent Escorts in Delhi, Escorts in Delhi, Escort Service in Delhi, We provide all types of female Delhi escorts including Russian escorts, model escorts and independent escorts in Delhi for 24x7.
Delhi Escorts
Escorts in Delhi

17:27  
Blogger Indbabes said...

Gurgaon Escort services is one of the best answers to the modern day stress that people deal with. Time has moved so fast that people have become engrossed in their corporate lives and forgot the real meaning of fun in total. Gurgaon Escorts

06:35  
Blogger Reshma Khan said...

Renu Das Kolkata Escorts Services has gorgeous females provides Independent Escorts Service in Kolkata call girls at 100% satisfaction with VIP models. Provided Kolkata escorts at our agency are professional in nature and are eager to serve you at your place.
Kolkata Escorts
Escorts in Kolkata

12:26  
Blogger Devayani Kaur said...

Sex-related desire perfectly into a truth.choice and we will proviHi Guys! We are advancing Wonderful data about reservation the best companion young girls of your de you the most beautiful companions.We Providing Top Advertising Ads Contact with site.
Escorts in Delhi Service | Delhi Escort City | Female Escort Service in Delhi/NCR

10:53  
Blogger Devayani Kaur said...

A commitment of gratefulness is all together For providing your popular opinions to us,By Your site i have properly secured collection of portion of the topic.Such a to an amazing level amazing publish, I am here to see this informative article as especially amazing weblog.
Devayani kaur | Priti Chawala

10:57  
Blogger Unknown said...

Its most popular blog and opinion, I getting fan you blog.
Bangalore Female Escorts

13:08  
Blogger Unknown said...

Wonderful blog, i like your opinions and ideas. Thanks for share with us.
Escorts Services in Bangalore

06:58  
Blogger Rasili RasiliGoa said...

Great blog, i would like to say thanks for share with us.
Russian Escorts Services in Delhi

10:57  
Blogger Unknown said...

Delhi Escorts Girls are very much bold and educated and they are all highly seducing in arrived from head to heels to you which enable all the perfection on your sexual lust to get to love with on demand and we are all happy to meet your all search completed at low rates on demand.

06:55  
Blogger Jangkrik Mewah said...

Bandar Ceme

Bandar Ceme Online

Bandar Ceme Terpercaya

Ceme Online

99 Ceme

10:59  
Blogger GInna Kelly said...

Bandar Ceme

Ceme Online

Bandar Ceme Online

Bandar Ceme Terpercaya

15:54  
Blogger Monalisa Roy said...

We are Independent escorts in Mumbai who have all kind of escort girls, people who provides such kind of services just call us.
Jesika Goa Escort

10:33  
Blogger Reshma Khan said...

I am Nansy Sharma an Top Class Independent Escorts in Delhi, Escorts in Delhi, Escort Service in Delhi, We provide all types of female Delhi Escorts including Russian escorts, model escorts and independent escorts in Delhi for 24x7.
Delhi Escorts
Escorts in Delhi
http://www.nansy.in/

19:11  
Blogger Gaurav Singh said...

My name is Gaurav Singh, I really very much impressed to this imei number se mobile kaise pata kare

02:52  
Blogger GInna Kelly said...

Bandar Ceme

Bandar Domino

Bandar Poker

Domino 99

Ceme 99

Ceme Online

Domino Online

Poker Online

09:16  
Blogger Ahuti Sharma said...

Watch Pictures of Escorts in Jaipur, Drinklovers.in Only at our Website Drinklovers.in

11:50  
Blogger GInna Kelly said...

Bandar Ceme Online

Bandar Ceme Terpercaya

Judi Ceme Online

Judi Ceme Terpercaya

Situs Bandar Ceme

Ceme Online Terbaik

Ceme Online Terpercaya

07:07  
Blogger Saanvi Sharma said...

I'm happy to find so many useful info here in the post.I really like it when people get together and share ideas. Great blog, keep it up!
Gurgaon Escorts
Beautiful Independent Escorts in Gurgaon

12:42  

Post a Comment

<< Home