0
1

More than 1 year has passed since last update.

退屈なことはRubyにやらせよう ~ファイル整理を自動化する~

Last updated at Posted at 2022-07-22

やりたいこと

8桁の日付が含まれている大量のファイルを、日付ごとのディレクトリに分類したい。

これを、、、
Screenshot.png

こうしたい。
Screenshot 1.png
Screenshot 2.png

膨大な量あるので。手動でカチカチなんてやってられない!

退屈なことは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から作るのが一番勉強になりますね!

ご指摘等ありましたら、お気軽にコメントください。

0
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1