ディレクトリ内のファイルが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
パッケージ?
他の人が説明したように、inotify
を使用する方が良い解決策です。スクリプトが失敗する理由を説明します。まず第一に、どの言語でプログラミングしていても、何かをデバッグしようとするときはいつでも、最初のルールは「すべての変数を出力する」ことです。
$ ls
file1 file2 file3
$ echo $PWD
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*
したがって、上記のように、$FILE
は実際には$PWD/*
に展開されます。したがって、ループはstring/home/terdon/foo/*
で1回だけ実行され、ディレクトリ内の各ファイルでは個別に実行されません。次に、md5sum
コマンドは次のようになります。
md5sum /home/terdon/foo/*
つまり、ターゲットディレクトリのすべてのファイルではなく、一度にmd5sum
を実行します。
問題は、グロブの展開を引用していて、展開されないようにすることです。
$ echo "*"
*
$ echo *
file1 file2 file3
variablesはほぼ 常に引用符で囲まれます である必要がありますが、グロブはグロブではなく文字列になるため、グロブは使用しないでください。
あなたがやろうとしていたことは:
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
コマンドラインから inotify-tools を確実に使用できます。このような :
inotifywait -r -m /dir/to/monitor/
-m
、--monitor
単一のイベントを受け取った後に終了する代わりに、無期限に実行します。デフォルトの動作では、最初のイベントが発生した後に終了します。
そして、ここにinotifywait
のmanファイルからコピーされた、継続的に監視するスクリプトがあります:
#!/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
inotify-tools
パッケージを使用して、フォルダー内のすべての変更をリアルタイムで監視できます。たとえば、次のように使用できるinotifywait
ツールが含まれています。
> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test
フラグを使用して、特定のイベントのみまたは特定のファイルをフィルタリングできます。 inotifywatch
ツールは、ファイルシステムの使用統計を収集し、各inotify
イベントの数を出力します。
他の例 ここ などを見つけることができます。
他のツールを使用して監視する場合は、find
を-mmin
パラメータ(変更された分)とともに使用できます。 2秒は0.033分と同じなので、次のように使用できます。
find . -type f -mmin 0.033
2秒間隔で監視する場合は、小切手を次のように囲みます。
while true
do
<your steps>
sleep 2
done
これは順次ファイルをテストし、ファイルが見つかるまで2秒間待機しますが、チェックを関数に変換することをお勧めします。
function _check_file()
{
SUM1=$(md5sum "$@")
sleep 2
SUM2=$(md5sum "$@")
if [ "$SUM1" == "$SUM2" ];
then
echo "$@: Identical"
else
echo "$@: Different"
fi
}
while
ループで使用できるもの:
while true
do
for FILE in "${PWD}/"*
do
if [ -f "$FILE" ]
then
_check_file "$FILE" &
fi
done
sleep 2
done
&
アンパサンドを使用して、バックグラウンドでチェックを実行し、ファイルチェックを並行して実行します。これは、ディレクトリにあるファイルの数によっては、パフォーマンスに影響を与える可能性があることに注意してください。
また、echo
行を変更して、ファイル名("$@"
)同一または異なるファイルが見つかるのを視覚化します。
#!/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//[^[:alpha:]]/}
r=$(md5sum "$f2")
if [ "$r" = "${!v}" ]; then
echo "Identical $f2"
else
echo "Different $f2"
fi
eval "${v}=\$r"
done <<< "$find"
done
sleep 2
done