This is a retrospective on my first python script, a command line program I use to sort my photos after returning on a photo expedition. It moves all files from my SD card into a specified folder in my computer, opens a spreadsheet which I fill out with “keeper” photos, and then reads that spreadsheet for which photos should be moved into another folder. It sorts and deletes photos according to that spreadsheet.
Problem: I come home from a big hike with a camera full of photos and two tired feet. I don’t want to spend precious seconds clicking through my computer’s folder system to the D drive, come up with a good name for the folder, CTRL-A all of the photos in my camera, and then paste them into a new folder. I just want to take a shower and drink a banana-based oat milkshake. Even worse, once I’ve picked the photos I want to keep and delete, I have to manually move those photos to the keepers folder.
Solution: Creating folders and moving files seems like a very command-liney problem to solve, creating a command line tool seems like a great reason to try out a new language, and python seems like the right language for this job. I watched a couple of tutorials, and kept this python cheatsheet on me while coding, and a couple of weekends later I have a nice little utility.
The first hurdle I ran into was actually just getting the photos off the camera. Previously I was using a USB cable between my computer and camera. The file system would open it like any other folder, but this ended up being far more complicated than anticipated. Connecting to the camera via a script this way requires understanding the camera’s firmware. I tried a couple different tricks to try to get my camera to show up in the command line logs, but I never figured it out. Instead, the far more optimal solution was to just eject the SD card from the camera and pop that into my computer. This is applicable for different kind of cameras and even saves me the step of getting the cable out of the camera bag! Sometimes the best solutions require a change in perspective.
After that, it was relatively smooth sailing. I have two main functions that require user input before being executed. `new_folder.py` does what it says on the tin and creates a new folder with the name being the user’s input plus the current date. My personal convention is to put the name of the place I was hiking, and the appended date ensures uniqueness and gives a good sense of time and place for the photos. The same script moves all photos from the SD card into that folder, generates another folder with the same name under my `Photos/Keepers` directory, creates a `descriptions.xlsx` in the Keepers folder for sorting photos, and opens all of these files and folders.
The next step in my flow is to manually look at each photo I want to keep and pop it into my spreadsheet, with the subject of the photo and the iNaturalist URL in their respective columns. iNaturalist is a wonderful platform that my photo expeditions are tightly integrated with, providing location, time, species and taxon data, and a wonderful community to boot. Once I’ve looked through all my photos, `move_photos.py` fulfills its namesake by reading the spreadsheet, moving the best photos to the keepers folder. It also deletes the RAW data photos as those are much bigger files.
I have a main file `new_exp.py` which I’ve popped into my environment variables PATH, so I can call it from anywhere. This script calls the new folder script and stays open until I’ve created and saved the spreadsheet, then calls the move photos script and sorts the photos.
I’m very happy with my new system! But there’s always room for improvement. I think the next steps would be to step through each photo and mark them within the program as a keeper or not. Perhaps with different tags as not all my photos are of wildlife. And now that I’ve got a set of “good” and “bad” photos, it would be interesting to train an AI on that dataset and see which photos an AI would choose. I don’t think photo sorting will ever be completely hands off for me, but it’s fun to tinker!