Comment afficher le nombre de lignes sorties par une commande en temps réel?

15

J'utilise svn exportdans le cadre d'un script de packager pour mon application, et il semble que cette commande, comme beaucoup d'autres, n'a pas de barre de progression.

J'ai deux choix pour le moment:

  • l'utiliser sans options, et regardez-le imprimer des milliers de lignes
  • en utilisant --quiet, et ne rien voir jusqu'à ce qu'il se termine.

Existe-t-il un moyen d'afficher au moins le nombre de lignes générées par la commande, en temps réel? Tel que:

Exporting SVN directory ... 1234 files

Et voir cet 1234 incrément de nombre en temps réel ? Je peux imaginer diriger la sortie vers une commande qui ferait exactement cela, mais laquelle?

Benjamin
la source

Réponses:

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

Ou mettez la section entre crochets dans un script shell. Notez que cela ne fonctionne que si votre shell prend réellement en charge l'opérateur de pré-incrémentation, comme bash ou ksh93 ou zsh. Sinon, vous devrez incrémenter $Ipuis l'imprimer (comme dans I=$((I+1));printf...). De plus, si ce printfn'est pas un builtin avec votre shell (c'est un builtin avec le bash actuel), vous pouvez utiliser echo -neou à la print -nplace pour de meilleures performances. Vous voulez juste supprimer la nouvelle ligne et avoir le \ r interprété comme un caractère d'échappement.

dannysauer
la source
Oh, je ne me ferai jamais apprendre le bashscripting avec toutes ses =différences et bizarreries laides et `=`. :) Pourquoi ne le remplaceraient-ils pas par un langage syntaxique de type python ...
Boris Burkov
Hé, je sais quoi! Vous pouvez ajouter un symbole de retour chariot à chaque nouvelle ligne que vous imprimez, et cela n'inondera pas l'écran, il remplacera simplement la ligne précédente.
Boris Burkov
C'est pourquoi printfse termine par un \r. Et que se passe-t-il si vous le faites echo -ne "$I\r"ou print -n "$I\r". :) J'ai utilisé printf, cependant, parce que par défaut, il n'imprime pas une nouvelle ligne à la fin, donc le \rretourne au début. Malheureusement, toutes les implémentations d'écho ne prennent pas en charge l' argument -eor -n.
dannysauer
1
Cela fonctionne également avec la version pdksh qu'OpenBSD utilise pour / bin / sh.
kurtm
1
+1, mais pour être tout à fait correct, vous devez passer readà read -r(car sinon une barre oblique inversée à la fin d'une ligne perturberait le comptage). Incidemment, avec un peu de travail, cela peut être adapté pour afficher également la dernière ligne de sortie, ce qui peut être utile pour certaines commandes.
ruakh
7

C'est une idée approximative, mais vous pouvez utiliser la pvcommande pour compter le nombre de lignes au fur et à mesure et les afficher à l'écran. pvparmi ses nombreux commutateurs, un -lcommutateur compte chaque ligne au fur et à mesure.

Exemple

Ici, j'utilise une boucle while pour simuler certains fichiers à partir de votre sortie 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 ] [      <=>             

Il continuera d'écraser la ligne de sortie comme ceci:

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

  24 0:00:47 [0.991/s ] [                                                <=>                                                      ]
slm
la source
Je n'étais pas au courant de pv. Hourra pour apprendre des trucs!
dannysauer
@dannysauer - pv vaut la peine d'apprendre quelque temps, il permet de mesurer et d'afficher tout ce qui passe par un tuyau.
slm
Je l'ai installé après avoir lu le commentaire et joué avec. Dix-huit ans d'utilisation de Linux, et il y a toujours toujours de nouvelles choses à découvrir. :)
dannysauer
0

Vous pouvez exécuter votre commande en arrière-plan en tant que travail et rediriger sa sortie standard (et éventuellement stderr) vers un fichier journal: command > logfile &&désigne la tâche (si stderr aussi, dites à la &>place de >).

Ensuite, vous pouvez utiliser l'utilitaire wordcount pour compter le nombre de lignes de votre fichier journal avec wc -l.

Pour montrer le changement d'état dans une ligne changeant dynamiquement, vous pouvez utiliser quelque chose comme while true; do echo -en '\r'; wc -l logfile; sleep 1; done, mais je ne peux pas forcer bash à dessiner \run retour chariot pour tuer le contenu de la ligne précédente.

Voir cette question, c'est presque un doublon: /programming/2388090/how-to-delete-and-replace-last-line-in-the-terminal-using-bash

Boris Burkov
la source
1
Mais il veut un affichage en temps réel qui continue à augmenter, ce qui n'est pas le cas de wc.
kurtm
@kurtm eh, ce qu'il veut beaucoup plus, c'est de ne pas avoir son écran inondé de résultats printf/print/echocomme le suggère Danny. :) Bien sûr, il pourrait utiliser less, mais je suppose qu'il peut se permettre de le dire à wc -l logfilechaque fois qu'il s'impatiente. Je pense que jouer avec ncursesou effacer l'écran est une exagération ici.
Boris Burkov
Hé bien oui. Il ne veut pas qu'il soit inondé, mais il veut connaître les progrès, sinon il pourrait simplement utiliser le --quiet.
kurtm
@kurtm see update: pouvez-vous aider à déboguer ma echo -e 'r'commande? Il devrait effacer le contenu de la ligne précédemment imprimé, afin qu'il change dynamiquement, mais je ne peux pas le forcer à le faire :(
Boris Burkov
Vous souhaitez également ajouter l'option n à écho qui supprime la nouvelle ligne de fin.
kurtm