Hires (Fließkomma) Fortschrittsbalken
Präambel
Entschuldigung für diese nicht so kurz Antwort.
Für Ungeduldige: Bitte testen Sie den Code unter Tun Sie es jetzt! (in der Mitte), mit Letzte animierte Demo (gegen Ende dieses Artikels.) und Praktisches Beispiel (am Ende).
Alle Demos hier verwenden read -t <float seconds> && break
anstelle von sleep
. Alle Schleifen können also durch Drücken von Return Schlüssel.
Einführung
Noch ein Bash-Fortschrittsbalken...
Da es hier bereits viele Antworten gibt, möchte ich noch einige Hinweise hinzufügen über Leistungen y Präzision .
1. Vermeiden Sie Gabeln!
Da ein Fortschrittsbalken dazu gedacht ist, zu laufen, während andere Prozesse arbeiten, muss es sich um eine schön Prozess...
Vermeiden Sie also die Verwendung von Gabeln wenn nicht benötigt. Beispiel: anstelle von
mysmiley=$(printf '%b' \\U1F60E)
Verwenden Sie
printf -v mysmiley '%b' \\U1F60E
Erläuterung: Wenn Sie var=$(command)
initiieren Sie einen neuen Prozess zur Ausführung command
und schickt seine Ausgabe zu variabel $var
sobald sie beendet ist. Dies ist sehr ressourcenintensiv. Bitte vergleichen Sie:
TIMEFORMAT="%R"
time for ((i=2500;i--;)){ mysmiley=$(printf '%b' \\U1F60E);}
2.292
time for ((i=2500;i--;)){ printf -v mysmiley '%b' \\U1F60E;}
0.017
bc -l <<<'2.292/.017'
134.82352941176470588235
Auf meinem Host, gleiche Arbeit der Zuweisung $mysmiley
(nur 2500 mal), scheinen ~135x langsamer/teurer zu sein, wenn man Gabel als durch die Verwendung eingebauter printf -v
.
Dann
echo $mysmiley
Also Ihr function
nicht drucken müssen (oder Ausgabe ) alles. Ihre Funktion muss seine Antwort auf eine variabel .
2. Ganzzahl als Pseudo-Gleitkomma verwenden
Hier ist eine sehr kleine und schnelle Funktion zum Berechnen von Prozenten aus ganzen Zahlen, mit ganzer Zahl und Antwort eine Pseudo-Fließkommazahl:
percent(){
local p=00$(($1*100000/$2))
printf -v "$3" %.2f ${p::-3}.${p: -3}
}
Verwendung:
# percent <integer to compare> <reference integer> <variable name>
percent 33333 50000 testvar
printf '%8s%%\n' "$testvar"
66.67%
3. Hires Konsolengrafik mit UTF-8:
Um diese Zeichen mit der Bash darzustellen, könnten Sie:
printf -v chars '\\U258%X ' {15..8}
printf "$chars\\n"
Dann müssen wir 8x verwenden string with
como graphic width
.
Tun Sie es jetzt!
Diese Funktion heißt percentBar
weil es einen Balken aus einem Argument macht, das in Prozenten (fließend) eingegeben wurde:
percentBar () {
local prct totlen=$((8*$2)) lastchar barstring blankstring;
printf -v prct %.2f "$1"
((prct=10#${prct/.}*totlen/10000, prct%8)) &&
printf -v lastchar '\\U258%X' $(( 16 - prct%8 )) ||
lastchar=''
printf -v barstring '%*s' $((prct/8)) ''
printf -v barstring '%b' "${barstring// /\\U2588}$lastchar"
printf -v blankstring '%*s' $(((totlen-prct)/8)) ''
printf -v "$3" '%s%s' "$barstring" "$blankstring"
}
Verwendung:
# percentBar <float percent> <int string width> <variable name>
percentBar 42.42 $COLUMNS bar1
echo "$bar1"
Um kleine Unterschiede aufzuzeigen:
percentBar 42.24 $COLUMNS bar2
printf "%s\n" "$bar1" "$bar2"
Mit Farben
Da die gerenderte Variable eine Zeichenkette mit fester Breite ist, ist die Verwendung von Farbe einfach:
percentBar 72.1 24 bar
printf 'Show this: \e[44;33;1m%s\e[0m at %s%%\n' "$bar" 72.1
![Bar with color]()
Kleine Animation:
for i in {0..10000..33} 10000;do i=0$i
printf -v p %0.2f ${i::-2}.${i: -2}
percentBar $p $((COLUMNS-9)) bar
printf '\r|%s|%6.2f%%' "$bar" $p
read -srt .002 _ && break # console sleep avoiding fork
done
||100.00%
clear; for i in {0..10000..33} 10000;do i=0$i
printf -v p %0.2f ${i::-2}.${i: -2}
percentBar $p $((COLUMNS-7)) bar
printf '\r\e[47;30m%s\e[0m%6.2f%%' "$bar" $p
read -srt .002 _ && break
done
![PercentBar animation]()
Letzte animierte Demo
Eine weitere Demo mit verschiedenen Größen und farbigen Ausgaben:
printf '\n\n\n\n\n\n\n\n\e[8A\e7'&&for i in {0..9999..99} 10000;do
o=1 i=0$i;printf -v p %0.2f ${i::-2}.${i: -2}
for l in 1 2 3 5 8 13 20 40 $((COLUMNS-7));do
percentBar $p $l bar$((o++));done
[ "$p" = "100.00" ] && read -rst .8 _;printf \\e8
printf '%s\e[48;5;23;38;5;41m%s\e[0m%6.2f%%%b' 'In 1 char width: ' \
"$bar1" $p ,\\n 'with 2 chars: ' "$bar2" $p ,\\n 'or 3 chars: ' \
"$bar3" $p ,\\n 'in 5 characters: ' "$bar4" $p ,\\n 'in 8 chars: ' \
"$bar5" $p .\\n 'There are 13 chars: ' "$bar6" $p ,\\n '20 chars: '\
"$bar7" $p ,\\n 'then 40 chars' "$bar8" $p \
', or full width:\n' '' "$bar9" $p ''
((10#$i)) || read -st .5 _; read -st .1 _ && break
done
Das könnte etwa so aussehen:
![Last animation percentBar animation]()
Praktisch GNU/Linux Probe: sha1sum
mit Fortschrittsbalken
Unter Linux finden Sie viele nützliche Informationen unter /proc
Pseudo-Dateisystem, also unter Verwendung zuvor definierter Funktionen percentBar
y percent
hier ist sha1progress
:
percent(){ local p=00$(($1*100000/$2));printf -v "$3" %.2f ${p::-3}.${p: -3};}
sha1Progress() {
local -i totsize crtpos cols=$(tput cols) sha1in sha1pid
local sha1res percent prctbar
exec {sha1in}< <(exec sha1sum -b - <"$1")
sha1pid=$!
read -r totsize < <(stat -Lc %s "$1")
while ! read -ru $sha1in -t .025 sha1res _; do
read -r _ crtpos < /proc/$sha1pid/fdinfo/0
percent $crtpos $totsize percent
percentBar $percent $((cols-8)) prctbar
printf '\r\e[44;38;5;25m%s\e[0m%6.2f%%' "$prctbar" $percent;
done
printf "\r%s %s\e[K\n" $sha1res "$1"
}
Ja, natürlich, 25 ms
Timeout bedeutet ca. 40 Aktualisierungen pro Sekunde. Dies könnte overkill aussehen, aber gut funktionieren auf meinem Host, und sowieso, dies kann getunnelt werden.
![sha1Progress sample]()
Erläuterung:
exec {sha1in}<
eine neue Dateideskriptor für die Ausgabe von
<( ... )
Verzweigte Aufgabe läuft im Hintergrund
sha1sum -b - <"$1"
sicherstellen, dass die Eingabe von STDIN ( fd/0
)
while ! read -ru $sha1in -t .025 sha1res _
Während keine Eingabe von der Unteraufgabe gelesen wird, wird in 25 ms
...
/proc/$sha1pid/fdinfo/0
Kernelvariable, die Informationen über Datei-Deskriptor 0 (STDIN) der Aufgabe $sha1pid
0 Stimmen
Siehe auch stackoverflow.com/questions/12498304/… für Beispiele der Kontrolllogik (Hintergrund einer Aufgabe und etwas tun, bis sie beendet ist).
4 Stimmen
Es gibt eine Reihe von Anforderungen, die wir beim Skripten häufig nützlich finden. Protokollierung, Anzeige des Fortschritts, Farben, schicke Ausgaben usw... Ich habe immer das Gefühl gehabt, dass es irgendeine Art von einfachem Skript-Framework geben sollte. Schließlich habe ich beschlossen, eines zu implementieren, da ich keines finden konnte. Möglicherweise finden Sie dies hilfreich. Es ist rein Bash, ich meine nur Bash. github.com/SumuduLansakara/JustBash
0 Stimmen
Sollte dies nicht verschoben werden nach unix.stackexchange.com?
0 Stimmen
Ich benutze gerne
pv
für alles, was gepiped werden kann. Beispiel:ssh remote "cd /home/user/ && tar czf - accounts" | pv -s 23091k | tar xz