これls $downloadDir -a1 | grep '[^.].*bin' | head -1
は間違った方法です。理由を確認するために、ダウンロード ディレクトリに と という名前のファイルがあり、それa.txt
が追加されたとします。を出力し、(\n ではなく実際の改行を使用して)を出力し、それを に細くし、最初の行以外をすべて削除して を残し、これは と一致しません。ディレクトリリストをスキャンするのではなく、 で終わるかどうかを確認する必要があります。これを行うには、次の 3 つの方法を紹介します。b.bin
c.bin
inotifywait
c.bin
ls
a.txt\nb.bin\nc.bin
grep
b.bin\nc.bin
head
b.bin
c.bin
$line
.bin
最初のオプション$line
は、リストではなくgrep を使用してチェックします。
if echo "$line" | grep -q '[.]bin$'; then
-q
オプションを使用してgrepの出力を抑制していることに注意してください。代わりに、ifコマンドに終了ステータスをチェックさせているだけです(一致が見つかった場合は成功、そうでない場合は失敗)。また、RE は行末に固定され、ピリオドは括弧内にあるため、実際のピリオドのみに一致します (通常、.
正規表現では任意の 1 文字に一致します)。 \.bin$
ここでも機能します。
2 番目のオプションは、変数の内容を編集するシェルの機能を使用して、で$line
終わるかどうかを確認し.bin
ます。
if [ "${line%.bin}" != "$line" ]; then
その部分は、そこにある場合、最後からトリミングされた"${line%.bin}"
$line の値を示します。それがそれ自体.bin
と同じでない場合は、 で終わっている必要があります。$line
$line
.bin
3 番目のオプションでは、bash の[[ ]]
式を使用してパターン マッチングを直接実行します。
if [[ "$line" == *.bin ]]; then
これは (IMHO) 最もシンプルで明確ですが、bash でのみ機能します (つまり、スクリプトを で開始する必要があります#!/bin/bash
)。
その他の注意: ファイル名の空白とバックスラッシュに関する問題を回避するために、while IFS= read -r line; do
二重引用符に関する @shellter の推奨事項を厳密に使用し、それに従ってください。
また、私は inotifywait にはあまり詳しくありませんが、AIUI の-e create
オプションは、ファイルの内容が完全に書き出されたときではなく、ファイルが作成されたときに通知します。タイミングによっては、部分的に書き込まれたファイルをコピーしてしまう可能性があります。
最後に、重複したファイル名のチェックはありません。foo.bin
という名前のファイルをダウンロードし、それがコピーされ、元のファイルを削除してから、という名前の別のファイルをダウンロードするとどうなるでしょうかfoo.bin
。スクリプトが現在のように、最初のfoo.bin
. これが望ましくない場合は、次のようなものを追加する必要があります。
if [ ! -e "$mbedDir/$line" ]; then
cp "$downloadDir/$line" "$mbedDir/$line"
elif ! cmp -s "$downloadDir/$line" "$mbedDir/$line"; then
echo "Eeek, a duplicate filename!" >&2
# or possibly something more constructive than that...
fi