From: Niklas Frykholm Date: 2006-05-30T16:29:40+09:00 Subject: Re: Directory Diff Script > Hi, > > I am after a directory diff script in Ruby, so I can compare all the > files in multiple directories. Does anybody know of such a script? > > Thanks. > > Nick. > I wrote this a while ago. I'm not sure exactly what you are after, but maybe you can use it as a starting point: #!/usr/bin/ruby IGNORE_EXT = %w(.scc .exe .xbe .lib .sbr .obj .dat .suo .pdb .res .idb .pch) IGNORE_BASE = %w(_darcs lib vultures buildlog.htm contentmeta.h rdiff) class String def indent return "\t" + self.gsub("\n", "\n\t") end end class Diff def diff(f1, f2) if f1.respond_to?(:to_ary) filelist(f1.to_ary, f2.to_ary) else if File.directory?(f1) and File.directory?(f2) dir(f1,f2) elsif File.file?(f1) and File.file?(f2) file(f1,f2) elsif File.directory?(f1) report_directory(f1, f2) elsif File.directory?(f2) report_directory(f2, f1) elsif File.file?(f1) report_file(f1, f2) elsif File.file?(f2) report_file(f2, f1) end end end def file(f1, f2) res = `diff #{f1} #{f2}` report_diff(f1, f2, res) if res != "" end def filelist(l1, l2) map = {} s = Struct.new(:f1, :f2) for f in l1 next if IGNORE_EXT.include?(File.extname(f)) next if IGNORE_BASE.include?(File.basename(f)) next if f[/~\d*$/] map[ File.basename(f) ] = s.new(f, nil) end for f in l2 next if IGNORE_EXT.include?(File.extname(f)) next if IGNORE_BASE.include?(File.basename(f)) next if f[/~\d*$/] b = File.basename(f) map[ b ] = s.new(nil, nil) if not map[ b ] map[ b ].f2 = f end for base, files in map if !files.f1 report_missing(files.f2) elsif !files.f2 report_missing(files.f1) else diff(files.f1, files.f2) end end end def dir(d1, d2) diff( Dir.glob(d1 + "/*").collect {|x| x.downcase}, Dir.glob(d2 + "/*").collect {|x| x.downcase} ) end # Reporting functions def report_directory(d, f) report(:type_mismatch, "#{d} is a directory, but #{f} is not") end def report_file(f, x) report(:type_mismatch, "#{f} is a regular file, but #{x} is not") end def report_missing(f) report(:missing_file, "#{f} has no corresponding file") if $report_missing end def report_diff(f1, f2, res) report(:diff, "\n#{f1} <--> #{f2}\n\n#{res.indent}") end def report(type, s) puts puts s end end require 'optparse' $report_missing = false $ignore_case = true opts = OptionParser.new opts.on('-m', '--missing', "Report missing files.") {|val| $report_missing = true;} rest = opts.parse(*ARGV) Diff.new().diff(rest[0], rest[1])