更新ファイルの発見

作成日:2000-11-05
最終更新日:

ftp が perl でできることがわかって一安心です。 そこで、ファイルの列挙について考えを戻します。

次に、更新すべきファイルをどのように列挙するかを考えます。 当初の目標では「最終更新をした日付と時刻をなんらかの形で覚えておき、その後更新された ファイルをコピーする」としていました。 ファイルの最終更新日を調べることはそれほど難しくはありません。 ファイルハンドルをファイル名から調べ、 そのファイルハンドルから所定の関数に従って読み出せばいいのです。 しかし、ファイルハンドルを経由する方法はどうもまだるっこしく感じます。 直接ファイル名から更新情報を得る手がかりはないか、調べてみました。

そこで利用できるのではないかと考えたのは、ファイルテスト演算子でした。 perl のファイルテスト演算子では、 いろいろな情報が調べることができます。 たとえば、-M オプションにより、ファイルが更新されてから現在まで どれだけの時間が経過しているかを調べることができます。 この経過時間は、日数単位で表現した小数で表されます。このとき、小数の単位は 1/86400、 すなわち1秒単位です。この単位で比較すればファイルの更新を調べることができます。 今回は、現在から24時間以内に更新・新規作成されたファイルをこれで調べます。

ついでにひとこと。 この -M 演算子ではディレクトリも拾いますから、ディレクトリを排除するために、 ファイルに限るという意味での -f 演算子でのテストを事前に行なっています。


# renovigo06.pl
# 2000-11-03
# MARUYAMA Satosi All Rights Reserved.
#

$_ = "tako";
chdir $_;

&dodir(':');

sub dodir {
	local($dir,$nlink) = @_;
	local($dev,$ino,$mode,$subcount);

	# トップレベルでは自分でリンク数を取得しなければならない

	($dev,$ino,$mode,$nlink) = stat(':') unless $nlink;

	# カレントディレクトリの全ファイルを得る。

	opendir(DIR,':') || die "Can't open $dir";
	local(@filenames) = readdir(DIR);
	closedir(DIR);

	if ($nlink == 2) {		# このディレクトリにはサブディレクトリはない
		for (@filenames) {
			next if $_ eq ':';
			next if $_ eq '::';
		}
	}
	else {							# このディレクトリはサブディレクトリを持っている。
		$subcount = $nlink - 2;
		for (@filenames) {
			next if $_ eq ':';
			next if $_ eq '::';
			$name = "$dir/$_";

			if ((-f $_) && (-M $_ < 1.0)) { # 24 時間以内で変更されたファイルに対して
				print "$name\n";
			}
			next if $subcount == 0;		# サブディレクトリをすべて処理したか

			#  リンク数を得ると共に、ディレクトリであるかをチェックする

			($dev,$ino,$mode,$nlink) = lstat($_);
			next unless -d _;

			chdir $_ || die "Can't cd to $name";

			&dodir($name,$nlink);
			chdir '::';

			$subcount--;
		}
	}
}

これで、変更するファイルが列挙できました。

まりんきょ学問所perl手習い > 更新ファイルの発見


MARUYAMA Satosi