
ディレクトリ内のファイルのいずれかが 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/
-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