ディレクトリ比較プログラム

30分プログラム、その152。ディレクトリ比較プログラム。
今日の仕事中に、バックアップしたコードと最新のコードを比較して、変更されたファイルを知りたいときに

$ for i in */*.java
do;
  cmp $i ../backup/$i
done

と書いたときに思いついた。

昔書いたことをすっかり忘れてた。(id:mzp:20070120)
まあ、今回はサブディレクトリにも対応してるしね。

使い方

$ ls ~/tmp/a
a  b  c  d

$ ls ~/tmp/b
b  c  d  e

$ ruby dcmp.rb ~/tmp/a ~/tmp/b
a:      missing
b:      diff
d:      diff
e:      new

ソースコード

関数の仮引数以外、全部定数にしても特に問題ないよなぁ、と思ったり思わなかったり。

#! /opt/local/bin/ruby -w
# -*- mode:ruby; coding:utf-8 -*-
#
# dcmp.rb -
#
# Copyright(C) 2007 by mzp
# Author: MIZUNO Hiroki <hiroki1124@gmail.com> 
# http://mzp.sakura.ne.jp/
#
# Timestamp: 2007/10/09 23:25:35
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Ruby itself.
#

def find_files(path)
  Dir[File.expand_path('**/*',path)].map{|s|
    s.sub(%r!\A#{path}/!,'')
  }
end

module Enumerable
  def zipTo(*items)
    self.map{|x|
      [x]+items
    }
  end
end

From,To,*_ = ARGV
fromFiles = find_files From
toFiles = find_files To

missing = (fromFiles - toFiles).zipTo(:missing)
new     = (toFiles - fromFiles).zipTo(:new)
diff    = (fromFiles & toFiles).select{|x|
  system "cmp #{From}/#{x} #{To}/#{x} > /dev/null"
  $? != 0
}.zipTo(:diff)
(missing + new + diff).sort{|a,b| a.first <=> b.first}.each{|filename,type|
  puts "#{filename}:\t#{type}"
}