Как отобразить количество строк, выводимых командой в режиме реального времени?


15

Я использую svn exportкак часть сценария упаковщика для своего приложения, и похоже, что эта команда, как и многие другие, не имеет какого-либо индикатора выполнения.

У меня есть два варианта на данный момент:

  • используя его без параметров, и смотрите, печатая тысячи строк
  • используя --quiet, и не оставляя ничего, пока не завершится.

Есть ли способ, по крайней мере, показать количество строк, выводимых командой, в режиме реального времени? Такие как:

Exporting SVN directory ... 1234 files

И увидеть это 1234 увеличение числа в реальном времени ? Я могу себе представить вывод команды в команду, которая будет делать именно это, но какую?

Ответы:


16
yourcommand | { I=0; while read; do printf "$((++I))\r"; done; echo ""; }

Или поместите раздел в квадратных скобках в сценарий оболочки. Обратите внимание, что это работает только в том случае, если ваша оболочка на самом деле поддерживает оператор преинкремента, например bash или ksh93 или zsh. В противном случае вам придется увеличить, $Iа затем распечатать его (как в I=$((I+1));printf...). Кроме того, если printfвы не встроенный в вашу оболочку (это встроенный в текущем bash), вы можете использовать echo -neили print -nвместо этого для повышения производительности. Вы просто хотите подавить символ новой строки и интерпретировать \ r как escape-символ.


О, я никогда не заставлю себя изучать bashscripting со всеми его уродливыми =и `=` различиями и причудами. :) Почему бы не заменить его языком, похожим на синтаксис Python ...
Борис Бурков

Эй, я знаю, что! Вы можете добавить символ возврата каретки к каждой новой строке, которую вы печатаете, и она не затопит экран, она просто перезапишет предыдущую строку.
Борис Бурков

Вот почему printfзаканчивается с \r. И что произойдет, если вы делаете echo -ne "$I\r"или print -n "$I\r". :) Я использовал printf, однако, потому что по умолчанию он не печатает новую строку в конце, поэтому \rпросто возвращается к началу. К сожалению, не все реализации echo поддерживают аргумент -eor -n.
dannysauer

1
Это также работает с версией pdksh, которую OpenBSD использует для / bin / sh.
Куртм

1
+1, хотя, чтобы быть абсолютно правильным, вы должны изменить readна read -r(так как в противном случае обратный слеш в конце строки будет мешать подсчету). Кстати, немного поработав, это может быть адаптировано для отображения последней строки вывода, что может быть полезно для некоторых команд.
Руах

7

Это грубая идея, но вы можете использовать pvкоманду для подсчета количества строк по мере их прохождения и отображения на экране. pvсреди множества переключателей есть -lпереключатель, который считает каждую строку по мере прохождения.

пример

Здесь я использую цикл while для имитации некоторых файлов из вашего SVN-вывода.

$ for i in $(seq 100); do echo "file$i"; sleep 2; done | pv -l -c >/dev/null
   3 0:00:05 [0.99/s ] [      <=>             

Он будет перезаписывать строку вывода следующим образом:

  18 0:00:36 [   0/s ] [                                     <=>                                                                  ]

  24 0:00:47 [0.991/s ] [                                                <=>                                                      ]

Я не знал о PV. Ура для изучения вещей!
dannysauer

@dannysauer - pv стоит потратить некоторое время на изучение, оно позволяет измерять и отображать все, что проходит через канал.
SLM

Я установил его после того, как прочитал комментарий и поиграл с ним. Восемнадцать лет использую Linux, и всегда есть что открыть для себя. :)
dannysauer

0

Вы можете запустить свою команду в фоновом режиме как задание и перенаправить ее стандартный вывод (и, возможно, stderr) в файл журнала: command > logfile &где &обозначает задание (если и stderr, скажем, &>вместо >).

Затем вы можете использовать утилиту wordcount для подсчета количества строк в вашем лог-файле wc -l.

Чтобы показать изменение состояния в одной динамически изменяющейся строке, вы можете использовать что-то вроде этого while true; do echo -en '\r'; wc -l logfile; sleep 1; done, но я не могу заставить bash нарисовать \rвозврат каретки, чтобы уничтожить содержимое предыдущей строки.

Посмотрите на этот вопрос, это почти дубликат: /programming/2388090/how-to-delete-and-replace-last-line-in-the-terminal-using-bash


1
Но он хочет показ в реальном времени, который продолжает увеличиваться, а это не то, что делает wc.
Куртм

@ kurtm Эх, он хочет гораздо больше, чтобы его экран не был заполнен результатами, printf/print/echoпредложенными Дэнни. :) Конечно, он мог бы использовать less, но я полагаю, он может позволить себе говорить wc -l logfileкаждый раз, когда он становится нетерпеливым. Я думаю, что игра с ncursesили очистка экрана - это перебор.
Борис Бурков

Ну да. Он не хочет, чтобы это затопило, но он хочет знать прогресс, иначе он мог бы просто использовать --quiet.
Куртм

@kurtm смотрите обновление: вы можете помочь отладить мою echo -e 'r'команду? Он должен стереть ранее напечатанное содержимое строки, чтобы он динамически изменялся, но я не могу заставить его это сделать :(
Борис Бурков

Вы также хотите добавить опцию n в echo, которая подавляет завершающий перевод строки.
Куртм
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.