Индикатор выполнения + ETA на той же строке с помощью команды pv

вступление

Я использую pv команда в трубе, чтобы показать индикатор выполнения. Я попробовал это с простым счетчиком:

for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | pv --progress --line-mode --size 100 --eta --timer

Это прекрасно работает, но я бы хотел, чтобы индикатор выполнения отображался в одной строке. Этот ответ объясняет, как это сделать.

Итак, я попробовал это:

for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | >&2 echo -en "\r"; pv --progress --line-mode --size 100 --eta --timer

Он остается на одной линии, но теперь он больше не обновляет ETA.

Вопрос

Как я могу получить ETA для обновления тоже?

Обновить

Теперь, когда iBug ответил на вопрос из предыдущего раздела, я понял, что у меня есть еще одно важное требование: stdout необходимо сохранить, чтобы его можно было использовать в следующей трубе. В моем конкретном случае мне нужно записать результат в файл (т.е. > some-file.txt)

1 ответ

Решение

Вы вводите неправильную команду.

for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | >&2 echo -en "\r"; pv --progress --line-mode --size 100 --eta --timer
                                                                               ^

Перед точкой с запятой pvТаким образом, вы фактически запускаете его на stdin/stdout, который является вашим терминалом. Вы должны сгруппировать дополнительные echo а также pv дать ему прочитать из for цикл:

for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | (>&2 echo -en "\r"; pv --progress --line-mode --size 100 --eta --timer)

Почему это не так для первой команды? Это потому, что весь for do done Предложение обрабатывается как одна команда, поэтому ее результат корректно передается pv, Во второй команде, однако, результат передается echo, Ты знаешь что echo ничего не читает со стандартного ввода.

Так как pv направляет stdin в stdout, числа также выводятся на терминал, который смешивается с указанием на stderr. Чтобы подавить нормальный вывод, перенаправьте его на /dev/nullитоговая команда

for (( i = 1 ; i <= 100 ; i++ )); do sleep 1; echo $i; done | (>&2 echo -en "\r"; pv --progress --line-mode --size 100 --eta --timer) > /dev/null

Если вы хотите перенаправить вывод в файл, просто измените /dev/null в конце команды.

Другие вопросы по тегам