Digital camera access is simple enough on GNU/Linux, but with a couple of tweaks here and there, it can be made even simpler.
Accessing digital cameras has always been simple on GNU/Linux. A large number of digital cameras are supported out of the box. When using the shell, arguably gphoto is the most convenient. Running gphoto with the "P" option autodetects the camera and downloads all the photos in it.
% gphoto2 -P
I keep all my photos in a "photos" directory with subdirectories in the "yyyy-dd-mm" format indicating the date taken.
First step of simplification is to automatically put each image into the correct location. Digital cameras put a lot of Exif information into each image, so extracting the date taken is quite straightforward. I use a simple tool called exif to do this.
Both gphoto2 and exif are available on Debian.
# apt-get install gphoto2 exif
After some trial and error, I figured that the images taken with my Canon PowerShot S3 IS have a tag 0x132 indicating the date each photo was taken.
% exif -t 0x132 IMG_0416.JPG EXIF entry 'Date and Time' (0x132, 'Date and Time')... Tag: 0x132 ('DateTime') Format: 2 ('Ascii') Components: 20 Size: 20 Value: 2007:10:22 06:05:49
What we want is in the "Value:" line. After filtering that line with grep, and using sed a couple of times, we can get the date in yyyy-dd-mm format.
% exif -t 0x132 IMG_0416.JPG | \ grep 'Value: ' | \ # Filter the line with "Value:" sed 's/.*Value: \(....:..:..\) .*/\1/' | \ # Get the yyyy:mm:dd part of the value line sed 's/:/-/g' # convert ":" to "-" 2007-10-22
If you want to understand exactly what each step is doing, try the above pipeline by adding one filter at a time.
Then I put together a small script to move each image in the current directory to ~/pictures/yyyy-mm-dd/ subdirectories where I want them.
gphoto2 -P for i in *.JPG do date=$(exif -t 0x132 $i | \ grep 'Value: ' | \ sed 's/.*Value: \(....:..:..\) .*/\1/' | \ sed 's/:/-/g') dir="/home/anuradha/pictures/test/$date" mkdir -p "$dir" mv -f "$i" "$dir" done
Notice that I use a test directory. I saved this in ~/bin/, and made it executable.
Now comes the fun part. After connecting the camera to the computer, I used "lsusb" to find out its vendor ID and product ID are 04a9:311a. The following udev rule in /etc/udev/rules.d/010_local.rules invokes the above script whenever this camera is plugged in.
ACTION=="add", BUS=="usb", \ SYSFS{idVendor}=="04a9", SYSFS{idProduct}=="311a", \ RUN+="/home/anuradha/bin/pictures.sh"
Well, matters are a little more complicated. Udev seems to invoke the script multiple times. So I added two extra "features" to stop that.
- Adding a lock file to prevent multiple simultaneous running of the script.
- Use a "timestamp" file at the end of the script, and not run again "too soon" (60 seconds turned out to be ok).
These made sure that the script is run only once when the camera is plugged in.
I used the number of seconds since the Unix Epoch given by the stat and date commands. If the timestamp file was created less than 60 seconds ago, the script aborts.
So here is the complete script:
#!/bin/bash set -e user=anuradha group=users pictures="/home/$user/Pictures" download="$pictures/.download" logdir="$pictures/log" log=$(date +"$logdir/%Y-%m-%d"); cooldown=60 lock=/tmp/.pictures.download lasttime=$lock.time # Avoid multiple simultaneous runs ln -s $lock $lock || exit 0 # Abort if we had run less than $cooldown seconds ago if [ -f "$lasttime" ] then t1=$(stat -c '%Z' $lasttime) t2=$(date +'%s'); dt=$((t2 - t1)) if [ $dt -lt $cooldown ] then rm -f $lock exit 0 fi fi # Take it slowly ;-) sleep 3 mkdir -p $download mkdir -p $logdir rm -f $download/* # Get the photos, all of them cd $download gphoto2 -P for i in *.JPG do date=$(exif -t 0x132 $i | \ grep 'Value: ' | \ sed 's/.*Value: \(....:..:..\) .*/\1/' | \ sed 's/:/-/g') dir="$pictures/$date" if [ ! -f "$dir/$i" ] then [ -d $dir ] || mkdir -p $dir chown $user:$group $i chmod 644 $i chown $user:$group $dir mv -f $i $dir echo "$date/$i" >> $log fi done cd rmdir $download # Add a timestamp touch $lasttime rm -f $lock exit 0
3 comments:
Nice. I was using f-spot on Ubuntu. It puts files in yyyy/mm/dd anyway this is good to know. Will try out gphoto.
Also this udev bit might help with a backup script that I wanted triggered when my external usb drive was connected.
Thanks.
Hi Dilantha,
Gphoto2 is one of the several programs that use the gphoto library. Digikam, gphotofs and f-spot all use gphoto library.
Be extra careful about multiple and simultaneous invocations of the script. As I have indicated in the post, a lock file and a timestamp will be good enough.
Ya I think I'll stick to my f-spot setup. I don't mind importing the photos manually once in a while.
But definitely going to look at the udev thing when I get some time.
Post a Comment