Wie wird die Anzahl der von einem Befehl ausgegebenen Zeilen in Echtzeit angezeigt?

15

Ich verwende svn exportals Teil eines Packager-Skripts für meine Anwendung, und es sieht so aus, als ob dieser Befehl, wie viele andere, keine Fortschrittsanzeige aufweist.

Ich habe im Moment zwei Möglichkeiten:

  • Verwenden Sie es ohne Optionen und sehen Sie zu, wie es Tausende von Zeilen druckt
  • Verwenden --quietund nichts sehen, bis es abgeschlossen ist.

Gibt es eine Möglichkeit, mindestens die Anzahl der vom Befehl ausgegebenen Zeilen in Echtzeit anzuzeigen? Sowie:

Exporting SVN directory ... 1234 files

Und sehen Sie dieses 1234 Zahleninkrement in Echtzeit ? Ich kann mir vorstellen, die Ausgabe an einen Befehl weiterzuleiten, der genau dies tun würde, aber welcher?

Benjamin
quelle

Antworten:

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

Oder setzen Sie den Abschnitt in Klammern in ein Shell-Skript. Beachten Sie, dass dies nur funktioniert, wenn Ihre Shell den Operator "Preincrement" (z. B. bash oder ksh93 oder zsh) tatsächlich unterstützt. Andernfalls müssen Sie es inkrementieren $Iund dann ausdrucken (wie in I=$((I+1));printf...). Wenn printfIhre Shell nicht über eine integrierte Funktion verfügt (dh über eine integrierte Funktion mit der aktuellen Bash-Funktion), können Sie echo -neoder print -nverwenden, um die Leistung zu verbessern. Sie möchten nur die neue Zeile unterdrücken und das Zeichen \ r als Escape-Zeichen interpretieren lassen.

dannysauer
quelle
Oh, ich werde mich nie dazu bringen, Bashskripting mit all seinen hässlichen =und `=` Unterschieden und Macken zu lernen . :) Warum sollten sie es nicht durch eine Sprache mit Python-ähnlicher Syntax ersetzen ...
Boris Burkov
Hey, ich weiß was! Sie können zu jeder neuen Zeile, die Sie drucken, ein Wagenrücklaufsymbol hinzufügen, das den Bildschirm nicht überflutet, sondern lediglich die vorherige Zeile überschreibt.
Boris Burkov
Deshalb printfendet das mit a \r. Und was passiert , wenn Sie das tun echo -ne "$I\r"oder print -n "$I\r". :) Ich habe es printfjedoch verwendet, da es standardmäßig so eingestellt ist, dass am Ende keine neue Zeile gedruckt wird, so dass \rnur zum Anfang zurückgekehrt wird. Leider unterstützen nicht alle Echo-Implementierungen das Argument -eoder -n.
Dannysauer
1
Dies funktioniert auch mit der pdksh-Version, die OpenBSD für / bin / sh verwendet.
Kurtm
1
+1, wenn auch absolut korrekt sein, sollten Sie ändern readzu read -r(da sonst am Ende einer Zeile würde Chaos mit der Auszählung eines Backslash). Übrigens kann dies mit ein wenig Arbeit angepasst werden, um auch die neueste Ausgabezeile anzuzeigen, was für einige Befehle nützlich sein kann.
Ruakh
7

Dies ist eine grobe Idee, aber Sie können den pvBefehl verwenden, um die Anzahl der Zeilen im Verlauf zu zählen und diese auf dem Bildschirm anzuzeigen. pvUnter den vielen Schaltern gibt es einen -lSchalter, der jede Zeile zählt, während sie durchläuft.

Beispiel

Hier verwende ich eine while-Schleife, um einige Dateien aus Ihrer SVN-Ausgabe zu simulieren.

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

Die Ausgabezeile wird weiterhin wie folgt überschrieben:

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

  24 0:00:47 [0.991/s ] [                                                <=>                                                      ]
slm
quelle
Ich wusste nichts von pv. Hurra fürs Lernen!
Dannysauer
@dannysauer - pv ist es wert, etwas Zeit mit dem Lernen zu verbringen. Es ermöglicht, dass alles, was durch ein Rohr geht, gemessen und angezeigt wird.
SLM
Ich habe es installiert, nachdem ich den Kommentar gelesen und damit gespielt habe. Achtzehn Jahre unter Linux, und es gibt immer wieder Neues zu entdecken. :)
dannysauer
0

Sie können Ihren Befehl im Hintergrund als Job ausführen und sein stdout (und optional stderr) in eine Protokolldatei umleiten: command > logfile &Dabei &bezeichnet job (wenn auch stderr, sagen Sie &>statt >).

Dann können Sie das Dienstprogramm wordcount verwenden, um die Anzahl der Zeilen in Ihrer Protokolldatei mit zu zählen wc -l.

Um die Zustandsänderung in einer sich dynamisch ändernden Zeile anzuzeigen, können Sie beispielsweise Folgendes verwenden while true; do echo -en '\r'; wc -l logfile; sleep 1; done, aber ich kann Bash nicht zwingen, einen \rWagenrücklauf zu zeichnen , um den Inhalt der vorherigen Zeile zu löschen.

Siehe diese Frage, es ist fast ein Duplikat: /programming/2388090/how-to-delete-and-replace-last-line-in-the-terminal-using-bash

Boris Burkov
quelle
1
Aber er möchte eine Echtzeitanzeige, die sich ständig erhöht, was wc nicht kann.
Kurtm
@kurtm eh, was er noch viel mehr will ist, dass sein Bildschirm nicht mit Ergebnissen überflutet wird, printf/print/echowie von Danny vorgeschlagen. :) Natürlich könnte er es gebrauchen less, aber ich nehme an, er kann es sich leisten, wc -l logfilejedes Mal zu sagen, wenn er ungeduldig wird. Ich denke, mit ncursesdem Bildschirm zu spielen oder ihn zu löschen, ist hier ein Overkill.
Boris Burkov
Nun ja. Er möchte nicht, dass es überflutet wird, aber er möchte den Fortschritt wissen, sonst könnte er einfach die --ruhe gebrauchen.
Kurtm
@kurtm siehe Update: Kannst du helfen, meinen echo -e 'r'Befehl zu debuggen ? Es sollte den zuvor gedruckten Inhalt der Zeile löschen, damit er sich dynamisch ändert, aber ich kann es nicht erzwingen :(
Boris Burkov
Sie möchten dem Echo auch die Option n hinzufügen, mit der der Zeilenumbruch unterdrückt wird.
Kurtm