我有一个非常简单的 bash 脚本,一旦新文件出现,它就会将数据同步到 USB 密钥。它写得不好,但它可以工作,但是我想最大限度地减少 CPU 时间,所以我使用了,sleep
但由于我使用 inotifywait 作为同步触发器,脚本为每个添加的新文件添加一秒钟的睡眠(并且有许多小文件)。我的解决方案是read
只读取 inotifywait 输出的最新行,我想通过将其管道到 tail -1 来完成,但它似乎不起作用。
#!/bin/bash
watched_path=".wine/drive_c/Data"
rm -r "$HOME/$watched_path/"*
inotifywait -r -m "$HOME/$watched_path" --format "%e %w%f" -e create -e moved_to |
while read action full_path; do
sleep 1
file=${full_path##*$watched_path}
echo "'$file' appeared in directory '$watched_path' via '$action'"
USB="USBKEY"
# Wait for USB to be connected before syncing.
until [ -e /media/$USER/$USB ]; do
echo "Connect USB for sync."
sleep 5
done
rsync -r "$HOME/$watched_path" /media/$USER/$USB
echo "Sync complete."
done
我同步整个文件夹,所以如果我错过一行 inotifywait 也没关系,但我需要在读取时在最新文件(以及最新行)之后同步它。这意味着从我停止发送文件的那一刻起,while 循环在再次挂起之前最多会再执行一次。
我怎样才能阅读仅最新行inotifywait 输出?如果您有其他建议来避免这个问题,这对我来说没问题,但我仍然对答案感兴趣。
答案1
我认为您要求的是更复杂的场景。您还没有描述如何识别“最后一个”到达的文件,因此这个文件在文件不活动 5 秒后就会超时,因为至少有一个文件已被传输。
- 设置标志=等待
- 并行:每当通知文件时,设置 flag = not_done
等到flag == not_done
开始循环
- 等待 USB 连接并开始同步过程 (
rsync
) - 如果传输了任何新文件,则设置 flag = not_done
- 否则
- 如果 flag == likely_done 则设置 flag =definitely_done 否则设置 flag = likely_done
- 如果我们花费的时间少于五秒,则等待剩余时间
- 等待 USB 连接并开始同步过程 (
- 循环直到 flag ==define_done
由于我们需要主进程和并行inotifywait
进程之间的 IPC,我会考虑将标志实现为一个文件,甚至可能是一组文件名。
据我所知这并不容易以确定是否rsync
传输了新文件。您可能需要比较之前和之后的目标目录内容。