Filtre vários itens da saída de um comando de longa execução

2
TLDR:

Como faço para executar o handbrakecli, obter progresso e ETA, canalizar para a caixa de diálogo sem piscar.

Detalhes:

Eu tenho um script que encontra todos os arquivos de vídeo em um diretório e, em seguida, executa handbrakecli sobre eles um de cada vez. Toda vez que o handbrakecli roda, ele mostra um monte de informações sobre o arquivo, etc. e depois a linha:

Encoding: task 1 of 1, 3.30 % (295.53 fps, avg 303.23 fps, ETA 00h02m54s)

No meu script eu canso o comando handbrakecli para alguns outros comandos para filtrar tudo, exceto o progresso e, em seguida, canalizo isso para dialogar assim:

Snippet 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;

Isso funciona bem. Ele mostra o progresso e não pisca. A segunda tarefa era apresentar uma maneira de mostrar tanto o progresso como o ETA e foi isso que eu criei:

Snippet 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

Isso funciona, mas a janela de diálogo pisca. Eu não sei se é relacionado ao desempenho (duvido) ou se todo o loop while read simplesmente não funciona bem com o diálogo.

Eu também tentei fazê-lo sem canalizar para a caixa de diálogo, mas isso apenas mostrou o diálogo uma vez e depois não o atualizou.

Snippet 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

Por fim, tentei isso:

Snippet 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;

E isso não funcionou bem.

Estou ciente de que há algumas coisas fundamentais erradas aqui.

    
por Peter Lee 30.07.2017 / 19:53

1 resposta

1

O snippet 2 está mais próximo. dialog --gauge opcionalmente procurará o marcador mágico XXX na entrada e, em seguida, lerá a nova porcentagem da linha seguinte e o novo prompt das linhas depois disso até um novo marcador.

Então você deve conseguir o que deseja com:

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;
    
por 30.07.2017 / 20:32