ファイルのバックアップをとりながら編集する

NetBSDというかpkgsrcのpkgviを参考に、ファイルのバックアップをとりながらそのファイルを編集するエディタコマンドのラッパーを書いてみました。編集後にファイルが更新されていたら、「ファイル名.bkYYYYMMDD」というファイルで元のファイルを保存します。もし「ファイル名.bkYYYYMMDD」が存在していたらバックアップはとりません(なので一日に2回編集した場合、1回目の編集後のファイルはバックアップされません)。
ファイル: bkvi.rb

#!/usr/bin/env ruby

class Editor
  def initialize
    @editor = ENV['EDITOR']
    @editor ||= 'vi'
  end

  def edit(filename)
    run(@editor, filename)
  end

  private
  def run(*args)
    Process.waitpid(fork { exec(*args) })
  end
end

if __FILE__ == $0
  require 'optparse'
  require 'tempfile'
  require 'fileutils'
  
  include FileUtils

  Version = '0.1a'
  OptionParser.new do |opt|
    opt.banner = "Usage: #{$0} filename"
    opt.parse!(ARGV)
    if ARGV.size < 1
      puts opt.help
      exit 1
    end
  end
  filename = ARGV.shift
  unless FileTest.file?(filename)
    $stderr.puts "#{$0}: no such file #{filename}."
    exit 1
  end
  
  editor = Editor.new
  ext = Time.now.strftime('.bk%Y%m%d')
  if FileTest.file?(filename + ext)
    editor.edit(filename)
    puts "#{$0}: backup file already exists."
    exit 0
  end
  
  tempfile = Tempfile.new(filename)
  open(filename, 'r') do |file|
    copy_stream(file, tempfile) 
  end
  tempfile.close
  
  editor.edit(tempfile.path)
  if cmp(filename, tempfile.path)
    puts "#{$0}: file unchanged."
  else
    mv(filename, filename + ext)
    mv(tempfile.path, filename)
    puts "#{$0}: file was modified."
  end
  rm(tempfile.path + '~', { :force => true })
  rm(tempfile.path + '.bak', { :force => true })
end