更新ファイルの発見

作成日: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