再帰的なファイルのバックアップ(Ruby)
次の動作をします。コピー先のディレクトリに
- ファイルがない(か変更されている)場合、ファイルを(上書き)コピーします。
- ディレクトリがない場合、再帰的にコピーします。
- ディレクトリがある場合、それが変更されていればそのディレクトリに入って、もう一度(再帰的に)最初から同じことをします。
- それ以外の場合は、何もしません。
配列 dir の中に [["コピー元のディレクトリの名前", "コピー先のディレクトリの名前"], [..., ...], ...] を書き込んでおきます。なお、配列に入れたコピー先のディレクトリが、予め存在していることが必要です。
基本的に Linux用です。Windows ではファイルの変更日時などの考え方が Linux とは異なるので、期待したような動作をしません。
require 'fileutils' def fcopy(snd, rsv) Dir.chdir(rsv) r_fn = Dir.glob("*") Dir.chdir(snd) Dir.glob("*").each do |fname| s = File.join(snd, fname) r = File.join(rsv, fname) mts = File.stat(s).mtime mtr = nil mtr = File.stat(r).mtime if r_fn.include?(fname) if FileTest.directory?(s) if r_fn.include?(fname) fcopy(s, r) if mts > mtr and FileTest.directory?(r) else puts "folder copy: #{fname}" FileUtils.cp_r(s, r) end elsif !r_fn.include?(fname) or mts > mtr puts "file copy: #{fname}" FileUtils.cp(s, r) end end end t = Time.now dir = [['/home/***/Pictures', '/media/***/Transcend/Linux Mint backup/Pictures'], ['/home/***/Documents', '/media/***/Transcend/Linux Mint backup/Documents']] dir.each do |d| next if File.stat(d[0]).mtime == File.stat(d[1]).mtime fcopy(d[0], d[1]) end printf("\nRuntime: %.3f [sec]\n", Time.now - t)
なお、コピー先のディレクトリやファイルは、コピー元にないものでも一切削除されません。コピー元を削除してもコピー先のファイル乃至ディレクトリは溜まっていく一方なので、要らないものは手で削除して下さい。
※追記
コピー元にファイルやディレクトリがなくなった場合に、コピー先も削除するバージョンを書きました。