web-dev-qa-db-ja.com

ファイルが変更されているかどうかを確認する

Linux(現在ext4ファイルシステムを使用)では、ファイルの内容が変更されているかどうかをすばやく確認するにはどうすればよいですかなし内容の読み取り

statコマンドは推奨されるアプローチですか?私は現在します

$ stat --format "%Y" hello.txt

その後、同じコマンドで同じ出力が得られるかどうかを確認できます。そうであれば、hello.txtは変更されていないと結論付けます。

私は、より確実にするために、より多くのパラメーターを投入したいと考えています。たとえば、ファイルサイズ、ファイル名などを追加すると、ファイルのより優れた「フィンガープリント」が提供されますか?

このトピックについて、TrueCryptがメタデータの変更を残さないようにしたためか、以前に使用していたTrueCryptボリュームが常に増分バックアッププログラムによって無視されたことを思い出します。 statによって返されたすべてのデータを変更することは確かに可能だと思います。したがって、ファイルの可能なすべての変更を取得することは保証できません。

10
DustByte

ファイルが通常の方法(アプリケーションでの編集、リビジョン管理システムからの新しいバージョンのチェックアウト、再構築など)で変更されたかどうかを検出する場合は、ファイルの変更時刻(mtime)が最後のチェック。それがstat -c %Yレポート。

変更時間はtouchコマンドで設定できます。ファイルが何らかの形で変更されたかどうかを検出したい場合(touchの使用、アーカイブの抽出など)、そのiノード変更時刻(ctime)が前回のチェックから変更。それがstat -c %Zレポート。 ctimeは、システム管理者以外は(そして、システムクロックを変更するか、ファイルシステムをバイパスしてディスクに直接アクセスすることによって)間接的にしか偽装できません。

Statコマンドの分解能は1秒のみです。したがって、ファイルが同じ1秒間に2回変更された場合、変更を見逃す可能性があります。 ext4のような新しいファイルシステムは、ナノ秒単位のより高いタイムスタンプを提供しますが、古いツールの一部はまだ追いついていません。

また、他のプログラムが任意の変更時刻を設定することも可能です。これがtouchコマンドでどのように発生するかを確認できます。

これら2つの可能性のいずれかが心配な場合は、ファイルサイズを確認することも悪くありません。これは、変更されたファイルを探すときにrsyncが行うことです。

3
Steve Sether

私は、より確実にするために、より多くのパラメーターを投入したいと考えています。

あなたが持っているのは正しい方法です。これが失敗する唯一の理由は、ファイルシステムが適切に更新されていない場合です。

もちろん、適切な知識と、パーティションにアクセスできるシステムへのrootアクセス権を持つユーザーが情報を変更して、ファイルが変更されていないかのように変更できると思いますlookただし、この場合は必ずサイズなども同じにしておいた方がいいでしょう。

1
goldilocks

指紋をより細かくします。

MacOS/BSDとGNUバージョンのstatの両方で同じ出力を生成する小さなラッパー関数を作成しました(また、gプレフィックス付きのHomebrewがインストールされたバージョンを検出します)。

init() {
  if command -v gstat > /dev/null; then
    # GNU coreutils with g prefix.
    statCmdArgs=("gstat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  Elif ! stat --version > /dev/null 2> /dev/null; then
    # MacOS/BSD stat
    statCmdArgs=("stat" "-f" "%N %z %b %u %g %i %l %m %c %B %k");
  else
    # Assume GNU version without prefix.
    statCmdArgs=("stat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  fi;
}

getFileStatus() {
  "${statCmdArgs[@]}" "$1";
}

init関数は、スクリプトの初期化中に一度呼び出され、検出のオーバーヘッドなしでgetFileStatusを繰り返し呼び出すことができます。

0
devstuff