やりたいこと
8桁の日付が含まれている大量のファイルを、日付ごとのディレクトリに分類したい。
膨大な量あるので。手動でカチカチなんてやってられない!
退屈なことはRubyにやらせよう。
コードと出力結果
require "date"
require "fileutils"
# 操作したいファイルの親ディレクトリを絶対パスで指定
PATH = "/Users/xxxx/整理したいビデオたち"
# 操作したいファイルをワイルドカードで指定
PATTERN = ["*.mp4", "*.mov"]
# ファイル名を取得
file_names = Dir.glob(PATTERN, base: PATH)
file_names.each do |file_name|
# ファイル名から日付を抽出できた場合のみ処理を行う
if date = file_name.slice(/(19|20)\d\d[01]\d[0-3]\d/)
# 日付を任意の形式に変換
dir_name = DateTime.parse(date).strftime("%Y年%-m月%-d日")
# 日付ごとのディレクトリを作成
Dir.mkdir("#{PATH}/#{dir_name}") if !Dir.exist?("#{PATH}/#{dir_name}")
# ファイルを移動
FileUtils.mv("#{PATH}/#{file_name}", "#{PATH}/#{dir_name}/#{file_name}")
# 成功時のメッセージ出力
puts "「#{file_name}」を「#{dir_name}」フォルダへ移動しました。"
else
# エラー時のメッセージ出力
puts "「#{file_name}」のファイル名に日付が含まれていません。"
end
end
% ruby sample.rb
「VID_20150221_124847.mp4」を「2015年2月21日」フォルダへ移動しました。
「VID_20150228_113337.mp4」を「2015年2月28日」フォルダへ移動しました。
「VID_20150228_145755.mp4」を「2015年2月28日」フォルダへ移動しました。
「VID_20150228_150005.mp4」を「2015年2月28日」フォルダへ移動しました。
「VID_20150302_144855.mp4」を「2015年3月2日」フォルダへ移動しました。
「VID_20150302_162343.mp4」を「2015年3月2日」フォルダへ移動しました。
「VID_20150302_172950.mp4」を「2015年3月2日」フォルダへ移動しました。
「VID_20150302_175424.mp4」を「2015年3月2日」フォルダへ移動しました。
「VID_20150311_160326.mp4」を「2015年3月11日」フォルダへ移動しました。
「VID_20150311_160452.mp4」を「2015年3月11日」フォルダへ移動しました。
「VID_20150318_160749.mp4」を「2015年3月18日」フォルダへ移動しました。
「VID_20150318_163331.mp4」を「2015年3月18日」フォルダへ移動しました。
「VID_20150318_163356.mp4」を「2015年3月18日」フォルダへ移動しました。
「VID_20150318_165508.mp4」を「2015年3月18日」フォルダへ移動しました。
「VID_20150404_180851.mp4」を「2015年4月4日」フォルダへ移動しました。
「VID_20150404_181140.mp4」を「2015年4月4日」フォルダへ移動しました。
「VID_20150405_182323.mp4」を「2015年4月5日」フォルダへ移動しました。
「VID_20150405_192210.mp4」を「2015年4月5日」フォルダへ移動しました。
「VID_20150405_202445.mp4」を「2015年4月5日」フォルダへ移動しました。
説明
ファイル名を配列に格納する
# 操作したいファイルの親ディレクトリを絶対パスで指定
PATH = "/Users/xxxx/整理したいビデオたち"
# 操作したいファイルをワイルドカードで指定
PATTERN = ["*.mp4", "*.mov"]
# ファイル名を取得
file_names = Dir.glob(PATTERN, base: PATH)
p file_names
# => ["VID_20150221_124847.mp4", "VID_20150228_113337.mp4", "VID_20150228_145755.mp4", "VID_20150228_150005.mp4", "VID_20150302_144855.mp4", "VID_20150302_162343.mp4", "VID_20150302_172950.mp4", "VID_20150311_160326.mp4", "VID_20150311_160452.mp4", "VID_20150318_160749.mp4", "VID_20150318_163331.mp4", "VID_20150318_163356.mp4", "VID_20150318_165508.mp4", "VID_20150404_180851.mp4", "VID_20150404_181140.mp4", "VID_20150405_182323.mp4", "VID_20150405_192210.mp4", "VID_20150405_202445.mp4"]
ディレクトリ以下のファイルのファイル名を、配列file_names
に入れます。
隠しファイル(.
で始まるファイル。Macだと厄介な.DS_STORE
など)は入りません。
ワイルドカードは配列なので複数指定可能です。
日付の抽出
/(19|20)\d\d[01]\d[0-3]\d/
(19|20)\d\d # 1900年から2099年
[01]\d # 01月から12月
[0-3]\d # 01日から31日
正規表現で、ファイル名から日付を抽出しています。
32日~39日が含まれてしまったりはしますが、個人で使う分にはこのくらいで問題ないかと。
ググるともっと精密なのが色々出てきます。
日付の無いファイルがあるときのエラー回避
if date = file_name.slice(/(19|20)\d\d[01]\d[0-3]\d/)
ファイルから日付が抽出できた場合のみ、処理を続けます。
抽出できない場合はエラーメッセージを出力して終わりです。
日付形式の変換
# 日付を任意の形式に変換
dir_name = DateTime.parse(date).strftime("%Y年%-m月%-d日")
日付の形式を変換。「○年○月○日」という形式で、月と日に0が付く場合は0を無くします。
例)
「20010401」
→ o「2001年4月1日」
→ x「2001年04月01日」
iCloud写真からデータを書き出しすると、この形式でサブディレクトリを作ってくれるので、それに倣っているだけです。
ディレクトリ作成とファイル移動
# 日付ごとのディレクトリを作成
Dir.mkdir("#{PATH}/#{dir_name}") if !Dir.exist?("#{PATH}/#{dir_name}")
# ファイルを移動
FileUtils.mv("#{PATH}/#{file_name}", "#{PATH}/#{dir_name}/#{file_name}")
日付ディレクトリの作成と、各ファイルの移動。
全て絶対パスで指定。
ディレクトリが存在していない場合のみ、ディレクトリを作成するようにして、重複を避けています。
最後に
Pythonで自動化する本を何冊か読んでみて、自分でも書きたかったのでRubyで書いてみました。やはり、自力で1から作るのが一番勉強になりますね!
ご指摘等ありましたら、お気軽にコメントください。