I took up photography as a hobby a few years ago. As soon as I began, I found myself unexpectedly drawn to the entire process. The complexity (and simplicity) of composition, the relationship of shutter speed, aperture, and iso. A hobby where you have fine tuned control over every step of the process. You could go the opposite way as well, throw everything in auto and let the camera fade into the background as your sense of curiosity guides you to the next subject.
I could go on forever about the beauty and intricacies of photography, but that's not what we're here for. I write this preamble to set the backdrop for today's script of interest. As mentioned above, it's easy to get lost in the minutia of the process. One spot I found myself spending many hours on is properly organizing my photo library. After a good amount of iterations and refinement, I believe I've finally settled on something simple and elegant.
As the format matured, the storage of film negatives converged towards a few basic setups. Either a box, drawer, or binder of some sort which stores sleeves of negatives, typically sorted by date. Sometimes delineated by format / film stock / camera. But the same principle applies, film goes in sleeve goes in container. With digital, we are no longer constrained by the limits of tangibility. This freedom brings its own set of issues. "I can store my files any way I want, but which way is the best?" I've seen the classic "dump everything in one folder and let Lightroom figure it out" work for a good amount of people. However, I see two issues with both this and other database driven methods. For starters, I don't have Lightroom. My current RAW editor of choice, Darktable doesn't organize photos. Second, I want my photos organized at the file system level, independent of any one program. The end result is a folder structure of the following format:
year
|-month
|-day
|-picture01
|-picture02
in practice,
2020
|-01
|-01
|-picture01
|-picture02
|-02
|-picture03
|-02
and so on.
Of course, creating and maintaining this layout by hand would be a real pain in the aperture. If only there were some way to sort these files automatically...
ExifTool , a collection of Perl modules that can do just about any exif-related operation. It may seem a bit, utilitarian at first glance. However, after looking through a few examples, it's easy to get ExifTool to do exactly what you need. I'll leave it to the curiosity of the reader to explore all of the tagging and sorting possibilities that ExifTool has to offer. Know that my application of the program is not even scratching the surface of ExifTool's utility.
exiftool '-Directory<CreateDate' -d %Y/%m/%d -r /directory/with/photos/*
is what I use to archive my photos as described above.
Well, I've got a way to sort my photos. Importing them should be easy enough using rsync . I'll just run the rsync command to import everything, then run my ExifTool command after that. Every single time I have new photos to import. Eh, we can do better! "Put them in a script!", you say. Then I'll only have to run one command every time! I assure you we can do even better than that! Here's where inotify-tools comes into play. More specifically, inotifywait will do the trick.
See, I don't want to run a command, press a button, what have you, every single time I have photos to import. It's just too much trouble! With inotifywait, I can have a script running at all times that watches a directory for changes (say, my mount directory). Then, upon mounting a drive 1 , look for a certain folder (say, DCIM), and begin importing and sorting. After all of that, unmount and power off my card reader. And all I had to do was plug the thing in!
#!/bin/bash
LIBRARY='/path/to/photo/library'
INCOMING="$LIBRARY/incoming"
WATCHDIR='/path/to/mount/directory'
MOUNTDIR="$WATCHDIR/disk"
CAMERADIR="$MOUNTDIR/DCIM"
watch_dir () {
while inotifywait -e CREATE $WATCHDIR
do
copy_photos
done
}
wait_for_dir () {
while [ ! -d "$WATCHDIR" ];
do
sleep 2
done
copy_photos
watch_dir
}
copy_photos () {
sleep 5
if [ -d "$CAMERADIR" ];
then
mkdir $INCOMING
rsync -ravP $CAMERADIR/* $INCOMING
cd $LIBRARY
exiftool '-Directory<CreateDate' -d %Y/%m/%d -r $INCOMING/*
rm -r $INCOMING
udiskie-umount --detach $MOUNTDIR
fi
}
if [ -d "$WATCHDIR" ];
then
watch_dir
else
wait_for_dir
fi
Once executed, the script will continuously run, only taking action when a new folder is created in my mount directory. 2 Once a directory is created (something is mounted), the directory structure is checked to see if it matches that of my camera's SD card. If so, make a temporary "incoming" directory, copy the contents of the SD card to it, and then put the files in their respective date-ordered directories. Once all of the copying and sorting is squared away, eject the SD card and power off the card reader using --detatch . Afterwards, go back to monitoring my mount directory for new folders.
I like it! I've been using this script for the past week and haven't run into any trouble. I've found my card reader provides me with an unintended benefit - it has a red LED on it that turns off when the script finishes. Now, I don't even need to double check the file system to see if the script completed (although I probably still should and will).
1. I have auto-mounting set up using udiskie.
2. udiskie defaults to /run/media/<user>