Bash
從長時間執行的命令的輸出中過濾多個項目
TLDR:
如何執行 handbrakecli,獲取進度和ETA,進入對話框而不閃爍。
細節:
我有一個腳本,它可以在一個目錄中找到所有影片文件,然後一次在它們上執行 handbrakecli。每次 handbrakecli 執行它都會吐出一堆關於文件等的資訊,然後是一行:
Encoding: task 1 of 1, 3.30 % (295.53 fps, avg 303.23 fps, ETA 00h02m54s)
在我的腳本中,我將 handbrakecli 命令傳遞給其他一些命令,以過濾除進度之外的所有內容,然後將其傳遞給對話框,如下所示:
片段 1
HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST" | \ stdbuf -o0 tr -s '\r' '\n' | \ stdbuf -o0 grep -oP '(?<=, )\d+(?=\.\d\d \%)' | \ dialog --gauge "$DIALOG_MSG" 10 70;
這工作正常。它顯示進度並且不閃爍。第二個任務是想出一種方法來顯示進度和預計到達時間,這就是我想出的:
片段 2
HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \ stdbuf -oL tr -s '\r' '\n' | \ while read -r str; do local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))"); local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)"); echo "$PROGRESS" | dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70; done
這有效,但對話視窗閃爍。我不知道它是否與性能有關(懷疑),或者整個while 讀取循環是否不能很好地與對話框一起使用。
我也嘗試在不通過管道連接到對話框的情況下進行操作,但它只顯示了一次對話框,然後根本沒有更新它。
片段 3
HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \ stdbuf -oL tr -s '\r' '\n' | \ while read -r str; do local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))"); local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)"); dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70 $PROGRESS; done
最後我嘗試了這個:
片段 4
HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \ stdbuf -o0 tr -s '\r' '\n' | ( read -r str; local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))"); local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)"); echo "$PROGRESS"; ) | dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70;
這根本沒有奏效。
我知道這裡有一些基本的問題。
片段 2 是最接近的。
dialog --gauge
將有選擇地在輸入中查找魔術標記XXX
,然後從下一行讀取新百分比,然後從之後的行讀取新提示,直到出現新標記。所以你應該得到你想要的:
HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | stdbuf -oL tr -s '\r' '\n' | while read -r str do REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))") PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)") echo -e "XXX\n$PROGRESS\n$DIALOG_MSG Time remaining: $REMAINING\nXXX" done | dialog --gauge "$DIALOG_MSG Time remaining: " 10 70;