ループの読み込み中にリアルタイム入力ストリームの最後の行のみを読み取る方法

ループの読み込み中にリアルタイム入力ストリームの最後の行のみを読み取る方法

新しいファイルが表示されたら、すぐにデータをUSBキーに同期する非常に単純なbashスクリプトがあります。うまく書かれていませんが、うまくいきますが、CPU時間を最小限に抑えたかったので、sleepinotifywaitを同期トリガーとして使用しているため、スクリプトは追加された新しいファイルごとに1秒のスリープモードを追加します(小さなファイルがたくさんあります)。私の解決策は、readinotifywait出力の最新の行だけを読むことです。 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を使用して1行を見逃しても問題はありませんが、読み取るときは最新のファイル(したがって最新の行)の後に同期する必要があります。これは、ファイル転送が中断された瞬間からwhileループが再び中断される前に最大1回実行されることを意味します。

どうやって読むことができますか?最新の行のみinotifywait出力?この問題を避けるための他の提案があれば大丈夫です。しかし、まだ答えに興味があります。

答え1

私はあなたが求めるのがより複雑なシナリオだと思います。 「最後」の到着ファイルを識別する方法を説明していないため、1つ以上のファイルが転送されたため、5秒間ファイルが無効になってからタイムアウトします。

  1. フラグ設定 = 待機
  2. パラレル:ファイルが通知を受け取るたびにフラグ= not_doneを設定します。
  3. フラグ== not_doneになるまで待ちます。

  4. ループ開始

    • USB接続を待って同期処理を開始します(rsync)。
    • 新しいファイルが転送されたら、フラグ= not_doneを設定します。
    • そうでなければ
      • フラグ==like_doneの場合はflag=determinly_doneを設定し、それ以外の場合はflag=like_doneを設定します。
    • 5秒もかからない場合は、残り時間を待ってください。
  5. フラグ==define_doneまで繰り返す

メインプロセスとパラレルプロセスの間にIPCが必要なので、inotifywaitフラグをファイルとして実装するか、ファイル名のセットとして実装することを考えてみましょう。

私が知る限り簡単ではないrsync新しいファイルが転送されたことを確認してください。前と後のターゲットディレクトリの内容を比較する必要があるかもしれません。

関連情報