dell19_88x31 Sony Styleロゴ_88_31 Apple Store

fileversions -- 複数ディレクトリのファイル比較


何だか使いまわしで似たディレクトリ構成が複数できちゃった場合。

仕様が違うんだから少しずつ違うのは当然なんですが共通の物も多い。
どれが最新というバージョンアップでなくて微妙な仕様違いという複数バージョンですから、 バージョンに枝が生えてるのでどれかのバグが取れても他のが修正漏れで残ったりしてイカンです。
なるべく同じファイルで両方で動くように処理を書き加えて同じファイルが両方にあるようにするんだけど、仕様が違うんだからいつも同じというわけではない。自分だけが編集してるわけでないし。

なーんて場合に、複数ディレクトリを指定すると同じ名前のファイル同士を比較しまくってバージョンを分類します。

●いまのところ表示幅を計算する部分の関数がバイト数を数えているだけなので「『全角』は2バイト」というshift_jisやeucのような文字コードならこのまま動きますがUTF-8のように2倍幅の文字が3バイトになったりする場合には縦がずれます。表示幅計算部分が関数として分けてあるので日本語を含むファイル名を使う場合にはここに処理を書き加えればいいでしょう。
●linuxなどのunix系で動かすように出来てますがwindowsならcygwinとかcoLinuxとかでこのまま動くことでしょう。unix系でもmacの場合はcompare関数のcmpのパスを変えるなどの必要があるかも。
●ファイル比較はunixに昔からある/usr/bin/cmpというコマンドを単に呼び出していますが表示幅のケースと同じくファイル比較部分も関数として分けてあるので必要に応じてここを書き換えればこのコマンドを呼ばなくなります。

●昔から欲しかったんだけどどこにも見つかんないからついに作った。

●コンソールコマンドですが小さい文字で画面いっぱいの大コンソールにするとかして使うのが吉。

●タダでコピーして使ってかまいませんし改造や転用やguiの付加等も自由ですが末尾にある僕のidのついたアフィリエイトリンクは何らかの形で有効な購入行動に結びつくように残してください。こういうのは何ライセンスって言うんだ?

使い方

fileversions dir ...

unix系のコマンドラインでディレクトリ名を並べて指定します。
カレントディレクトリを指定する場合には "." を指定します。

fileversions

  1. fileversions : ダウンロードしやすいようにファイル名の後ろに「.txt」をくっつけたんで、リネームして使ってください。chmod +x fileversions して実行可にします。

fileversions
2008-11-20
-h オプションを作った。
2008-11-19
-c オプションを作った。
2008-11-17
あんまり仮版なんでだいぶ綺麗にした。公開してしまう。
2008-11-16
作った。むきー。


#!/usr/bin/perl

# fileversions -- compare files in multi directories -- 2008/11/16-20 by i16

@arg=@ARGV;


$condensed=$header=0;

sub badcommandline {
	print STDERR "usage: fileversions (-ch) dir ...\n\n-c: condensed\n-h: header\n";
	exit -1;
	}

while(substr($arg[0],0,1) eq "-") {
	$p=substr($arg[0],1);
	while((length($p) > 0) && (($c=substr($p,0,1)) ne "-")) {
		if($c eq "c") { $condensed=1;}
		elsif($c eq "h") { $header=1;}
		else { badcommandline();}
		$p=substr($p,1);
		}
	shift @arg;
	}


@dir=@arg;
$dirs=$#dir+1;

$DEBUG=0;

if(!$dirs) { badcommandline();}

sub compare { my($f1,$f2)=@_;
	return 1 if -s $f1 != -s $f2;
	return system("/usr/bin/cmp","-s","$f1","$f2") / 256;
	}

sub ls { my($d)=@_; my($i,$f,@w);
	if(substr($d,-1)=="/") { $d=substr($d,0,-1);}
	opendir(D,$d);
	for($i=0;defined($f=readdir(D));) {
		if(($f ne ".") && ($f ne "..")) {
			$w[$i++]=$f;
			}
		}
	closedir(D);
	return sort @w;
	}

sub printwidth { return length($_[0]);}



for($i=0;$i<$dirs;$i++) {
	if(substr($dir[$i],-1) ne "/") { $dir[$i].="/";}
	@wkwk=&ls($dir[$i]);
	for($maxw=$count=0;$f=shift @wkwk;$count++) {
		$wk=&printwidth($f);
		$maxw=$wk if $maxw<$wk;
		$ls[$i][$count]=$f;
		}
	$lss[$i]=$count;
	$maxwidth[$i]=$maxw;
	}
for($i=0;$i<$dirs;$i++) { $ix[$i]=0;}



sub fchar { my($f);
	return " " if $name eq "";
	$f=$dir[$i].$name;
	return "/" if -d $f;
	return "." if -f $f;
	return "?";
	}


sub alldone { my($i);
	for($i=0;$i<$dirs;$i++) { return 0 if $ix[$i]<$lss[$i];}
	return 1;
	}

sub pw { my($w,$s)=@_; printf("%-*s",$w,substr($s,0,$w));}
sub pi { my($s)=@_; pw($maxwidth[$i]+2,$s);}

if($header) {
	if($condensed) {
		$t=0;
		do {
			for($i=1;$i<$dirs&substr($dir[0],-$t-1) eq substr($dir[$i],-$t-1);$i++) {
				;
				}
			if($dirs&&$i>=$dirs) {$t++;}
			} while($dirs&&$i>=$dirs);
		for($i=0;$i<$dirs;$i++) {
			printf("%*d:%s\n",$i*2+1,$i,substr($dir[$i],0,-$t));
			}
		for($i=0;$i<$dirs;$i++) {
			if($i) {
				if($i%10) { print " ";}
				else {print ($i/10)%10;}
				}
			print $i%10;
			}
		print " x ----+----1----+----2----+----3\n";
		}
	else {
		for($i=0;$i<$dirs;$i++) {
			print " " if $i;
			pi($dir[$i]);
			}
		print"\n\n";
		}
	}

while(!&alldone()) {
	for($name="",$i=0;$i<$dirs;$i++) {
		if($ix[$i]<$lss[$i]) {
			$wk=$ls[$i][$ix[$i]];
			if(($name eq "") || (($name cmp $wk) > 0)) {
				$name=$wk;
				}
			}
		}
	$curver="A";
	for($i=0;$i<$dirs;$i++) {
		if($name ne $ls[$i][$ix[$i]]) {
			if($condensed) { print "-";}
			else { pi("-");}
			}
		else {
			$chr=&fchar();
			if($chr ne ".") {
				if($condensed) { print $chr;}
				else { pi($name.$chr);}
				}
			else {
				for($j=0;$j<$i;$j++) {
					if($name eq $ls[$j][$ix[$j]-1]) {
						if(!compare($dir[$j].$name,$dir[$i].$name)) {
							$chr=$ver[$j];
							last;
							}
						}
					}
				if($j>=$i) {
					$chr=$curver;
					$curver=chr((ord($curver)-ord('A')+1)%26+ord('A'));
					}
				$ver[$i]=$chr;
				if($condensed) { print $chr;}
				else { pi($name.";".$chr);}
				}
			$ix[$i]++;
			}
		print " ";
		}
	print chr((ord($curver)-ord('A')-1)%26+ord('A'));
	if($condensed) {print" ".$name;}
	print "\n";
	}

# donations ... you may use this program at no charge,
# but if you are about to buy a book or dvd or pcs or lcds or plasmavisions or others,
# please go to an amazon through following links. thank you (^_^)/ -- i16
#
# jp http://www.amazon.co.jp/exec/obidos/redirect-home/i16jp-22
# de http://www.amazon.de/exec/obidos/redirect-home/i16jp0f-21
# fr http://www.amazon.fr/exec/obidos/redirect-home/i16jp0a-21
# ca http://www.amazon.ca/exec/obidos/redirect-home/i16jp0b-20
# uk http://www.amazon.co.uk/exec/obidos/redirect-home/i16jp-21
# us http://www.amazon.com/exec/obidos/redirect-home/i16jp-20
#
#end of fileversions -- i16

fileversions


i16(愛一郎) -- 受託開発お請け出来ます。
ドネーション用広告類 -- アマゾンとか楽天とかのアフィリエイトリンクなので書籍購入や通販で雑貨や機材の購入などついでがあるかたはこちらからお願いできればという感じです。僕はまるで悠々自適ではなく、税金や大企業の収益でどっか国や自治体や企業のどっかの研究所に雇われていてソフトを作って配って市民に還元してるとかじゃなくて、勤め人でなく基本的な収入の無い全くの無所属の個人なので(収入があれば税務署に申告してるのでちゃんと収入があるときは個人事業主ということになりますが収入が無いときとかは全然アウトですお金かお仕事ください)、タダで配ってるだけだと基本的には生活が成り立たってないんで、もしついでがあればですが、よろしくです (^_^)/