ディレクトリからファイルの変更を検出する Bash スクリプト

ディレクトリからファイルの変更を検出する Bash スクリプト

ディレクトリ内のファイルのいずれかが 2 秒間隔で変更されたかどうかを検出するスクリプトを作成しようとしています。これまでのところ、次のようになっています。

#!/bin/bash
for FILE in "${PWD}/*"
do
    SUM1="$(md5sum $FILE)"
    sleep 2
    SUM2="$(md5sum $FILE)"
    if [ "$SUM1" = "$SUM2" ];
    then
        echo "Identical"
    else
        echo "Different"
    fi
done

これは値「同一」を 1 回だけ出力します。各ファイルをチェックし、各ファイルに対して「同一」または「異なる」を出力するようにします。

編集: インストールせずにこれを行うことはできますか?inotify-toolsパッケージ?

答え1

使用できますinotify ツール必ずコマンドラインから、例えば次のようにします:

inotifywait -r  -m /dir/to/monitor/

から男のinotifywait

-m--monitor

単一のイベントを受け取った後に終了するのではなく、無期限に実行します。デフォルトの動作は、最初のイベントが発生した後に終了することです。

以下は、man ファイルからコピーした、継続的に監視するスクリプトですinotifywait

#!/bin/sh
while inotifywait -e modify /var/log/messages; do
  if tail -n1 /var/log/messages | grep apache; then
    kdialog --msgbox "Blah blah Apache"
  fi
done

答え2

他の人が説明しているように、 を使用するのがinotifyより良い解決策です。スクリプトが失敗する理由を説明します。まず、どの言語でプログラミングしているかに関係なく、何かをデバッグしようとするときは常に、最初のルールは「すべての変数を出力する」ことです。

$ ls
file1  file2  file3
$ echo $PWD    
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*

したがって、上で見たように、$FILEは実際には に展開されます$PWD/*。したがって、ループは で1回だけ実行されます。 /home/terdon/foo/*ディレクトリ内の各ファイルを個別に実行するのではなく、md5sumコマンドは次のようになります。

md5sum /home/terdon/foo/*

つまり、md5sumターゲット ディレクトリ内のファイルごとに実行されるのではなく、すべてのファイルに対して一度に実行されます。

問題は、glob 展開を引用しているため、展開されなくなることです。

$ echo "*"
*
$ echo *
file1 file2 file3

その間変数ほぼ常に引用されるグロブはグロブではなく文字列になるため、そうすべきではありません。

あなたがやろうとしていたことは次のとおりです:

for FILE in "${PWD}"/*; do ...

ただし、ここで を使用する理由はありません$PWD。何も有用なものが追加されません。上記の行は次の行と同等です。

for FILE in *; do

また、シェル変数に大文字を使用しないでください。これらはシステム設定の環境変数に使用されるため、独自の変数は小文字のままにしておくことをお勧めします。

これらすべてを念頭に置いて、スクリプトの実用的な改良版を以下に示します。

#!/bin/bash
for file in *
do
    sum1="$(md5sum "$file")"
    sleep 2
    sum2="$(md5sum "$file")"
    if [ "$sum1" = "$sum2" ];
    then
        echo "Identical"
    else
        echo "Different"
    fi
done

答え3

このinotify-toolsパッケージを使用すると、フォルダー内のすべての変更をリアルタイムで監視できます。たとえば、inotifywait次のように使用できるツールが含まれています。

> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test

フラグを使用して、特定のイベントのみ、または特定のファイルをフィルタリングできます。このツールは、ファイルシステムの使用状況の統計を収集し、各イベントinotifywatchの数を出力します。inotify

他のツールで監視する場合は、パラメータ (変更された分)findを使用できます。2 秒は 0.033 分に相当するため、次のように使用できます。-mmin

find . -type f -mmin 0.033

答え4

#!/bin/bash
# pass one or more folders as arguments
while true; do
  for f in "$@"; do
    date
    echo "Checking $f and subfolders"
    find=$(find "$f" -type f)
    while read -r f2; do
      # strip non-alphanumeric from filename for a variable var name
      v=${f2//[^[:alnum:]]/}
      r=$(md5sum "$f2")
      if [ "$r" = "${!v}" ]; then
        echo "Identical $f2"
      else
        echo "Different $f2"
      fi
      eval "${v}=\$r"
    done <<< "$find"
  done
  sleep 2
done

関連情報