inotifywait 忽略監視目錄中的新文件夾
我正在嘗試使用 inotifywait 來觀看文件夾(/shares/Photos),當它檢測到添加到文件夾中的 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
但沒有任何區別,我真的不確定從這裡去哪裡。任何建議/幫助將不勝感激。
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
or的目錄的事件.jpeg
才會被處理。不會處理髮生但與過濾器不匹配的目錄創建事件,因此
inotifywait
不會呼叫inotify_add_watch(2)
此事件以及稍後在 this 中發生的任何事情。因此,在這個子目錄中永遠不會有事件被監視。我找不到使用
--includei
或其他類似選項來表達“僅針對這些正則表達式或任何目錄處理事件”的方法。更新:建議一種解決方法
所以讓它工作的方法似乎必須在命令之外進行過濾。
grep
如果不是 tty,GNU將緩衝它的輸出,所以添加--line-buffered
.這將受到使用者輸入的影響(如文件名中的空格)。為了緩解這種情況,
/
需要在目錄和文件名之間使用分隔符(在文件名中無效)。由於目錄部分方便地包含尾隨/
,因此只需刪除格式字元串中的空格就足夠了(以及進一步的變數處理和重用,如changed_abs
)。同時,我正在糾正過濾以字元串or結尾的文件名的意圖,不包括這些字元串,並可能改進對內部有空格的目錄的初始處理(的影響,但以後還有更多需要修復)。OP 應該真正用腳本中的引號保護所有相關變數(jpg``jpeg``changed_abs``small_dir``{ }
不替換引號)。代替:
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)
) ,必須盡快將一個新監視添加到該目錄,因為它可能會失去其中的後續事件(競爭條件)。它甚至記錄在BUGS部分:inotifywait``inotifywait
遞歸目錄監視程式碼中存在競爭條件
$$ … $$可能無法修復。
- 較新版本的
inotifywait
,當至少在核心> = 5.9 上以 root (或足夠特權)執行時,應該能夠使用該fanotify(7)
工具,但我無法設法讓我的版本inotifywait
使用它,儘管應該是在支持下編譯並具有足夠新的核心。在fanotify(7)
將要使用的系統上,結合該--filesystem
選項,假設這可以消除必須為每個較新目錄執行操作的需要,並使 OP 的方法基於過濾--includei
工作。