なんだかんだで8年近くカメラをやっている私ですが、昔と今で異なる現像ソフトを使っています。そして取り込み時のフォルダ名のルールを変えてしまったため、フォルダ名が滅茶苦茶になってきました。具体的には、Nikon ViewNX で取り込んでいた頃は3桁の連番(001/, 002/, ...
)に保存していたのですが、Adobe Lightroom を使うようになってからは YYYYMMDD (20160101/, 20160102/, ...
) という規則で取り込んでいます。
いい加減気持ち悪くなってきたので、日付毎に写真をフォルダ分けする Ruby スクリプトを書きました。これを使うと、写真の Exif 情報から日時を取得し、その日時に対応したフォルダに写真を移動できます。例えば2016年1月21日に撮影された写真なら 20160121
というフォルダに移動します。
以下、スクリプトと使い方です。
検証環境
- Windows 10 64bit (Build 10240)
- ruby 2.2.3p173 (2015-08-18 revision 51636)
導入手順
- 何はともあれ Ruby を実行できるようにしておく。
- Ruby 実行環境がない人は以下の記事を参考に作ってください。
-
gem install thor
で Thor gem をインストール。 - 後述のスクリプトを適当な名前 (仮に
organize_photos.rb
とする) で保存する。 - スクリプトと同じディレクトリに Exiv2 - Image metadata library and tools からダウンロードした "Windows executable" のバイナリを保存する。
- RAW や JPEG 画像の Exif データから撮影日時を抽出するために利用。
- exifr という gem の方が手軽ですが、これは JPEG と TIFF しか扱えないので NG でした。
-
ruby organize_photos.rb mv {移動元フォルダ} {移動先フォルダ}
で移動を実行。
ここまででファイル構成が以下のようになっていれば OK です。
$ ls .
exiv2.exe libexpat.dll organize_photos.rb
スクリプト
require 'date'
require 'fileutils'
require 'thor'
class OrgnizePhoto < Thor
desc 'move SRC_DIR dest_DIR', 'Move files in SRC_DIR to dest_DIR'
option :extensions, default: 'nef,dng,jpg,jpeg'
option :date_format, default: '%Y%m%d'
option :force, type: :boolean, default: true
option :noop, type: :boolean, default: false
def mv(src_dir, dest_dir)
get_files(src_dir, options[:extensions]).each do |src|
date = extract_date(src, options[:date_format])
dest = "#{dest_dir}/#{date}/" + src.sub(src_dir, '')
opts = { force: options[:force], noop: options[:noop] }
move src, dest, opts
end
end
private
def get_files(dir, extensions)
Dir.glob("#{dir}/*.{#{extensions}}")
end
def extract_date(file, date_format)
exif = `exiv2.exe -q -Pnv #{file}`
if /DateTimeOriginal\s+(\d{4}:\d{2}:\d{2})\s+(\d{2}:\d{2}:\d{2})/ =~ exif
DateTime.parse("#{$1.tr(':', '-')} #{$2}").strftime(date_format)
else
false
end
end
def move(src, dest, options)
dest_dir = File.dirname(dest)
begin
unless Dir.exist?(dest_dir)
FileUtils.mkdir_p dest_dir
puts "Created #{dest_dir}"
end
FileUtils.move(src, dest, options)
puts "#{src} -> #{dest}"
rescue Exception => e
p "#{src} -> #{dest} ... #{e.inspect}"
end
end
end
OrgnizePhoto.start(ARGV)
実行例
$ ruby -Eutf-8 organize_photos.rb mv --noop f:/Pictures/001/ f:/Pictures/
f:/Pictures/001/RIMG0408.jpg -> f:/Pictures/20080707/RIMG0408.jpg
f:/Pictures/001/RIMG1817.jpg -> f:/Pictures/20080907/RIMG1817.jpg
f:/Pictures/001/RIMG1828.jpg -> f:/Pictures/20080908/RIMG1828.jpg
f:/Pictures/001/RIMG1840.jpg -> f:/Pictures/20080909/RIMG1840.jpg
補足
- 私が Nikon および Ricoh ユーザーなので、拡張子は
.nef, .dng, .jpg, .jpeg
ぐらいしか対応してません。- 他のメーカーのカメラをお使いの方は、拡張子を実行時のオプション
--extensions
に追加してください。 - スクリプト内の
option :extensions, default: 'nef,dng,jpg,jpeg'
の中に直接追加しても OK。
- 他のメーカーのカメラをお使いの方は、拡張子を実行時のオプション
- オプション
--noop
を付けた場合は、ファイルの移動先が表示されるだけで実際に移動は発生しません。 - かなり急いで書いたので、変なバグがあるかもしれません。気づいた方はコメントか編集リクエストをください。
- 誰か僕に D5 か D500 を買ってください。