Skip to content

Instantly share code, notes, and snippets.

@thekindofme
Created May 4, 2010 16:18
Show Gist options
  • Save thekindofme/389604 to your computer and use it in GitHub Desktop.
Save thekindofme/389604 to your computer and use it in GitHub Desktop.
require 'find'
require 'exifr'
require "fileutils"
class PhotoOrganizer
SOURCE_DIRS = ["/media/truecrypt1/nick_picks"]
EXCLUDES = ["CVS"]
DEST_DIR = "/media/truecrypt1/dow_jones"
DEST_DIR_OTHER = "/media/truecrypt1/dow_jones/other"
DUPLICATES = "duplicates"
IMAGE_FILE_EXTS = [".jpg", ".jpeg"]
STATS_LOG_FILE = "stats.log"
DUPLICATES_LOG_FILE = "duplicate_files.log"
def run
FileUtils.mkdir_p "#{DEST_DIR}#{File::SEPARATOR}#{DUPLICATES}"
FileUtils.mkdir_p DEST_DIR_OTHER
@files_with_valid_exif_data = []
@files_with_invalid_exif_data = []
@files_with_invalid_ext = []
@duplicate_files = []
@files_with_same_timestamp = []
@unique_files = []
walk_the_source_dir
write_log_file
end
def write_log_file
log = <<EOS
Files with valid EXIF data = #{@files_with_valid_exif_data.size}
Files with invalid EXIF data = #{@files_with_invalid_exif_data.size}
Files with invalid_ext = #{@files_with_invalid_ext.size}
Duplicate files = #{@duplicate_files.size}
Files with same timestamp = #{@files_with_same_timestamp.size}
Unique files = #{@unique_files.size}
EOS
File.open("#{DEST_DIR}#{File::SEPARATOR}#{STATS_LOG_FILE}", 'w') {|f| f.write(log) }
File.open("#{DEST_DIR}#{File::SEPARATOR}#{DUPLICATES_LOG_FILE}", 'w') {|f|
@duplicate_files.each { |entry|
f.puts "duplicate of #{entry[:original]} found in #{entry[:duplicate]}"
}
}
end
def walk_the_source_dir
SOURCE_DIRS.each do |dir|
Find.find(dir) do |path|
if FileTest.directory?(path)
if EXCLUDES.include?(File.basename(path))
Find.prune # Don't look any further into this directory.
else
next
end
else
#p "processing #{path}..."
process_file path
end
end
end
end
def process_file source_path
file_ext = File.extname(source_path.downcase)
if IMAGE_FILE_EXTS.include? file_ext
exif_file = EXIFR::JPEG.new(source_path)
if exif_file.exif? && exif_file.date_time
@files_with_valid_exif_data << source_path
copy_file(source_path, exif_file.date_time)
else
p "#{source_path}: doesn't contain valid EXIF data, hence using ctime"
@files_with_invalid_exif_data << source_path
copy_file(source_path, File.new(source_path).ctime)
end
else
p "#{source_path}:doesn't have a valid file ext. Coping to Other"
@files_with_invalid_ext << source_path
FileUtils.cp source_path, "#{DEST_DIR_OTHER}#{File::SEPARATOR}#{File.basename(source_path)}"
end
end
def copy_file source_path, timestamp
dest_dir = "#{DEST_DIR}#{File::SEPARATOR}#{timestamp.year}#{File::SEPARATOR}#{timestamp.strftime("%b")}#{File::SEPARATOR}#{timestamp.strftime("%d - %a")}"
dest_file_path = "#{dest_dir}#{File::SEPARATOR}#{timestamp.strftime("%p %I:%M:%S")}"
FileUtils.mkdir_p dest_dir
if File.exists?(dest_file_path)
if FileUtils.compare_file(source_path, dest_file_path)
@count = 0
@duplicate_files << {:duplicate => source_path, :original => dest_file_path}
FileUtils.cp source_path, "#{DEST_DIR}#{File::SEPARATOR}#{DUPLICATES}#{File::SEPARATOR}#{File.basename(source_path)}-#{rand(51252)}"
else #two or more uniuqe files with the same timestamp
@count = @count + 1
@files_with_same_timestamp << source_path
FileUtils.cp source_path,"#{dest_file_path} - #{@count}"
end
else
@unique_files << source_path
@count = 0
FileUtils.cp source_path, dest_file_path
end
p "copied #{source_path} to #{dest_file_path}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment