Ruby Script for sorting photos by year and month
Today, I worked on a personal project in Ruby that would sort my ever expanding library of family photos into a common folder structure. I like the way iTunes handles this by sorting them into sub-folders as /year/month the photo was taken so that’s what I went with.
#!/usr/bin/env ruby
# Summary:
# This utility will take each jpg, png, gif in the specified directory, including sub-directories, and
# copy it to the specified output directory (optional) for the year and month the photo was taken/created.
# (example: ./unsorted/image.jpg -> ./sorted/2013/10/image.jpg)
#
# Code Author: Jason Savage
#------------------------------------------
require 'exifr'
require 'fileutils'
def run()
return if ARGV.length < 1
# get dir argument
in_dir = ARGV[0]
out_dir = ARGV[1] || in_dir
# fix path if on windows
in_dir = in_dir.gsub(%r{\\}) { "/" }
out_dir = out_dir.gsub(%r{\\}) { "/" }
puts 'in: ' + in_dir, 'out: ' + out_dir
if Dir.exist? in_dir
# loop through each *.jpg in the folder and move to dir/#{year}/
Dir.glob( in_dir + '/**/*.{jpg,png,gif}') do |file|
move_file(out_dir, file)
end
end
end;
def move_file(dir, file)
date_time = EXIFR::JPEG.new(file).date_time || File.mtime( file )
if date_time != nil && date_time.year != ''
# get path as #{dir}/year/month
out_dir = File.join(dir, date_time.year.to_s, zero_pad(date_time.month.to_s))
# create #{dir}/year/month if it doesn't exist?
FileUtils.mkdir_p out_dir unless Dir.exist?(out_dir)
# check if image file name is already used
i = 1
ext = File.extname(file)
fname = File.basename(file, ext)
while File.exist? File.join(out_dir, fname + ext)
fname = File.basename(file, ext) + '_' + i.to_s
i += 1
end
# move file to new directory
FileUtils.cp( file, File.join(out_dir, fname + ext) )
end
end
def zero_pad(str)
if str.to_f < 10
return '0' + str
end
return str
end
# run script
run if __FILE__ == 'photo_date_sort.rb'