inotifywaitは監視ディレクトリの新しいフォルダを無視します。

inotifywaitは監視ディレクトリの新しいフォルダを無視します。

フォルダ(/shares/Photos)を表示するためにinotifywaitを使用しようとしていますが、そのフォルダに追加されたjpgが検出された場合は、サブディレクトリ($ small_dir)でサイズを変更する必要があります。写真マネージャの下には多くのjpgサブフォルダがあります。

木はこんな感じです。

shares
  -Photos
      -Folder 1
      -Folder 2
       .
       .
       .

既定では、誰かが画像をコピーするたびにfolder 1新しいサブフォルダを作成し、画像のサイズを変更し、小さいバージョンをそのフォルダに配置する必要があります。

その後、ツリーは次のようになります。

shares
  -Photos
      -Folder 1
          -Resized
      -Folder 2
       .
       .
       .

これまで私のコードは次のようになります。

inotifywait -mr --timefmt '%m/%d/%y %H:%M' --format '%T %w %f' -e close_write /shares/Photos --includei "\.jpg|\.jpeg" |
while read -r date time dir file; do
    changed_abs=${dir}${file}
    small_dir=${dir}${target}/
    
    printf "\nFile $changed_abs was changed or created\n  dir=$dir \n  file=$file \n  small_dir=$small_dir \n"
    
    # Check if the $small_directory exists, if not create it.
    if [ -d "$small_dir" -a ! -h "$small_dir" ]
    then
        echo "$small_dir found, nothing to do."
    else
        echo "Creating $small_dir"
        mkdir $small_dir
        chmod 777 $small_dir
    fi
    
    # Check to see if the file is in $small_dir, if it is, do nothing.  
    if [ "$dir" = "$small_dir" ]; then
        printf "\nFile is in the $small_dir folder, nothing to do\n"
    else
        printf "\nResizing file into the $small_dir folder\n"
        # Code to resize the image goes here.
    fi
        
done

Photosデフォルトでは動作しますが、スクリプトの実行中に新しいサブフォルダを作成すると、inotifywaitがこれを無視して何もしないという壁にぶつかりました。

close_writeと交換してみましたが、createあまり違いはありませんでした。

どんなアドバイスや助けにも感謝します。

ベストアンサー1

OPは以下を使用しています。

inotifywait -mr --timefmt '%m/%d/%y %H:%M' --format '%T %w %f' -e close_write /shares/Photos --includei "\.jpg|\.jpeg" |

関連文書--includei言った(太い強調私):

--includei <pattern>

イベント処理名前付きPOSIX正規表現と一致するファイルのサブセットにのみ適用され、大文字と小文字を区別しません。

これは「表示イベント」ではなく「イベント処理」です。実際には、名前に含めるか処理する.jpgディレクトリのイベントのみを意味します。.jpeg

発生したがフィルタと一致しないディレクトリ生成イベントは処理されないため、inotifywait呼び出されません。inotify_add_watch(2)今回の事件とそれ以降に起こったすべてのことについて。したがって、このサブディレクトリではイベントは監視されません。

--includei「この正規表現に対してのみイベントを処理します。または任意のディレクトリに」。


修正する:提案されたソリューション

したがって、機能させる方法は、コマンドの外部をフィルタリングする必要があるようです。grepttyでない場合、GNUは出力をバッファリングするので--line-buffered

これはユーザー入力(ファイル名のスペースなど)の影響を受けます。これを軽減するには、/ディレクトリとファイル名の間に区切り文字を使用する必要があります(ファイル名には影響しません)。ディレクトリ部分には便利な末尾が含まれているので、/フォーマット文字列からスペースを削除するだけで十分です(たとえば、追加の変数の処理や再利用も可能ですchanged_abs)。これまでファイル名のフィルタリング意図を修正しています終わり文字列がjpgあるかjpeg含むこれらの文字列を含み、内部にスペースがあるディレクトリの初期処理を改善することができます(changed_abs影響を与えますが、small_dir後で修正する必要がある方が多い)。 OPは実際にはスクリプト内のすべての関連変数を引用符で囲む必要があります({ }引用符を変更せずに)。

変える:

inotifywait -mr --timefmt '%m/%d/%y %H:%M' --format '%T %w %f' -e close_write /shares/Photos --includei "\.jpg|\.jpeg" |
while read -r date time dir file; do
    changed_abs=${dir}${file}
    small_dir=${dir}${target}/

そして:

inotifywait -mr --timefmt '%m/%d/%y %H:%M' --format '%T %w%f' -e close_write /shares/Photos |
    grep --line-buffered -Ei '/[^/]*\.(jpg|jpeg)$' |
while read -r date time changed_abs; do
    [ -d "$changed_abs" ] && continue # a directory looking like a picture filename was written to: skip this event
    dir="${changed_abs%/*}/"
    file="${changed_abs##*/}"
    small_dir="${dir}${target}/"

まだ完全にテストされていませんが、これはアイデアです。ディレクトリテストが必要かどうかはわかりませんが(イベントが発生していないように見えますclose_write)、問題にはなりません。


ノート

  • 明確でない場合は、検出された各ディレクトリ生成イベントに対してアクション()を実行する必要がinotify_add_watch(2)あります。inotifywaitinotifywaitできるだけ早く次のイベント(競合条件)がない可能性があるため、このディレクトリに新しい調査を追加してください。でも録音されています。間違い部分:

    再帰ディレクトリに競合状態があり、観察されたコード[...]が変更されない可能性があります。

  • 最新バージョンは、inotifywait最小カーネル 5.9 以降で root (または十分な特権を持っている) として実行する場合は、次のものを使用できる必要があります。fanotify(7)inotifywait機能はサポートされていますが、十分に新しいカーネルをサポートする必要がありますが、私のバージョンではそれを使用することはできませんでした。私が使用するシステムでfanotify(7)この--filesystemオプションを組み合わせると、新しいディレクトリごとにこれを行う必要がなくなり、OPのアプローチがフィルタリングに基づいて機能するようになると仮定します--includei

おすすめ記事