如何在 while 读取循环中仅读取实时输入流的最后一行

如何在 while 读取循环中仅读取实时输入流的最后一行

我有一个非常简单的 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 秒后就会超时,因为至少有一个文件已被传输。

  1. 设置标志=等待
  2. 并行:每当通知文件时,设置 flag = not_done
  3. 等到flag == not_done

  4. 开始循环

    • 等待 USB 连接并开始同步过程 ( rsync)
    • 如果传输了任何新文件,则设置 flag = not_done
    • 否则
      • 如果 flag == likely_done 则设置 flag =definitely_done 否则设置 flag = likely_done
    • 如果我们花费的时间少于五秒,则等待剩余时间
  5. 循环直到 flag ==define_done

由于我们需要主进程和并行inotifywait进程之间的 IPC,我会考虑将标志实现为一个文件,甚至可能是一组文件名。

据我所知这并不容易以确定是否rsync传输了新文件。您可能需要比较之前和之后的目标目录内容。

相关内容