[Risolto] Progress bar output comando

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Avatar utente
Pehua
Prode Principiante
Messaggi: 241
Iscrizione: martedì 19 aprile 2022, 9:02
Desktop: Ubuntu
Distribuzione: Ubuntu 22.04.4 LTS
Sesso: Maschile

[Risolto] Progress bar output comando

Messaggio da Pehua »

Come si fa una semlice progress bar per output di un qualsiasi comando?

La cosa che mi sarebbe utile è una percentuale sul rimanente tempo e una progress bar anche semplici asterischi che seguono la percentuale.

Es: dal comando cp origin destin

Avere un indicazione del genere:

79% alla fine *******************************
78% alla fine *****************************
etc...

o il contrario:
1% alla fine *
2% alla fine **

echo "Ready!!"

Ma rimanendo in un unica riga.

Non so da dove partire :D
Ultima modifica di Pehua il mercoledì 22 febbraio 2023, 12:31, modificato 1 volta in totale.
Al di la delle impostazioni culturali :birra:
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1627
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: Progress bar output comando

Messaggio da nuzzopippo »

un "man echo" Ti darebbe tutte le notizie necessarie, per fare ciò che chiedi occorrerebbe dare un "echo -ne" e terminare la stringa con "\r", il parametro "n" serve ad impedire l'inserimento del carattere di fine riga, il parametro "e" server per abilitare l'interpretazione dei caratteri di escape, la notazione "\r" indica il ritorno ad inizio riga (è un carattere di escape), esempio:

Codice: Seleziona tutto

zP:~$ cat fai_echo.sh
#!/bin/bash

barra=""
for i in 1 2 3 4 5 6 7 8 9 10
do
	perc=$((100*$i/10))
	barra="$barra#" 
	echo -ne "$perc% alla fine $barra\r"
	sleep 2s
done
echo
NzP:~$ ./fai_echo.sh
100% alla fine ##########
NzP:~$
Nota lo echo vuoto, è dato per creare una nuova riga, riavresti il prompt sulla riga scritta, altrimenti
:ciao:

[Edit] Dormivo, la percentuale calcolala così:

Codice: Seleziona tutto

perc=$((10*(10-$i)))
Fatti non foste a viver come bruti ...
Avatar utente
Pehua
Prode Principiante
Messaggi: 241
Iscrizione: martedì 19 aprile 2022, 9:02
Desktop: Ubuntu
Distribuzione: Ubuntu 22.04.4 LTS
Sesso: Maschile

Re: Progress bar output comando

Messaggio da Pehua »

nuzzopippo ha scritto:
mercoledì 22 febbraio 2023, 5:00
un "man echo" Ti darebbe tutte le notizie necessarie, per fare ciò che chiedi occorrerebbe dare un "echo -ne" e terminare la stringa con "\r", il parametro "n" serve ad impedire l'inserimento del carattere di fine riga, il parametro "e" server per abilitare l'interpretazione dei caratteri di escape, la notazione "\r" indica il ritorno ad inizio riga (è un carattere di escape), esempio:

Codice: Seleziona tutto

zP:~$ cat fai_echo.sh
#!/bin/bash

barra=""
for i in 1 2 3 4 5 6 7 8 9 10
do
	perc=$((100*$i/10))
	barra="$barra#" 
	echo -ne "$perc% alla fine $barra\r"
	sleep 2s
done
echo
NzP:~$ ./fai_echo.sh
100% alla fine ##########
NzP:~$
Nota lo echo vuoto, è dato per creare una nuova riga, riavresti il prompt sulla riga scritta, altrimenti
:ciao:

[Edit] Dormivo, la percentuale calcolala così:

Codice: Seleziona tutto

perc=$((10*(10-$i)))
Ciao grazie!!!

Avevo cercato prima di postare ed uno che avevo trovato funzionante era questo:

Codice: Seleziona tutto

sek=10
echo "10 Seconds"

while ((sek--)); do
    printf "One moment please: %d" "$sek"
    sleep 1
    printf "\r%b" "\033[2K"
done
echo "Ready!"
Devo dire che il tuo mi piace di piu e sei stato chiaro nello spiegare il comando echo -ne \r, ma due cose non capisco:

1 Parlando del tuo codice, come avanza la $barra#

2 In generale, anche di esempi trovati con ciclo while etc, ma con counter a numeri da uno a dieci o simili, come applicarli all' output di un comando qualsiasi che richiede "tempo", una copia di un file grande per esempio o qualcosa del genere.

Non so come applicarci questo codice (parlo del tuo che mi piace di piu e quasi lo capisco).

Grazie mille in qualsiasi caso della risposta e dell eventuale approfondimento.

EDIT

Ho provato cosi (script.sh è il nome dello script con il tuo codice):

Codice: Seleziona tutto

cp "video.mp4" ~/Scrivania/ | ~/Scrivania/script.sh
Forse funziona , è un caso che coincide con i tempi?
Se il codice ha uno sleep di 2 secondi come può coincidere con la dimensione del file che si sta copiando?

Se ho sbagliato fammi sapere, vorrei capire come abbinare il tuo codice ad un comando :)
Al di la delle impostazioni culturali :birra:
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1627
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: Progress bar output comando

Messaggio da nuzzopippo »

Pehua ha scritto:
mercoledì 22 febbraio 2023, 6:48
1 Parlando del tuo codice, come avanza la $barra#
È piuttosto semplice, alla riga 3 definisco una variabile "barra" che altro non è che una stringa vuota

Codice: Seleziona tutto

barra=""
all'interno del ciclo for aggiungo un carattere "#" ridefinendo la variabile "barra" come una stringa che ha il precedente contenuto della stessa variabile ($barra) ed un carattere "#", L'ISTRUZIONE È

Codice: Seleziona tutto

barra="$barra#"
Pehua ha scritto:
mercoledì 22 febbraio 2023, 6:48
2 In generale, anche di esempi trovati con ciclo while etc, ma con counter a numeri da uno a dieci o simili, come applicarli all' output di un comando qualsiasi che richiede "tempo", una copia di un file grande per esempio o qualcosa del genere.
Non esiste una regola generale, bisogna valutare caso per caso cosa è utile mostrare e se mostrare, non sempre è semplice farlo, non sempre è il caso di farlo, di norma, per utilizzare canonicamente una "barra di avanzamento" bisogna conoscere quantitativamente il "peso" da raggiungere e la quantità realizzata ad ogni passaggio, nel caso di un file di grandi dimensioni, p.e., la dimensione in bytes del file e la quantità di bytes elaborati ad ogni singola passata, quindi calcolarsi la percentuale elaborata ad ogni singolo passaggio con la solita formula x= (quantità elaborata / quantità totale) * 100, quindi costruire una stringa contenente il segnale di tale avanzamento, tipo un carattere "#" ogni 5 punti, ad esempio, sarebbero 20 caratteri alla percentuale 100.
Ovviamente, tale considerazione vale per qualsiasi frangente, tipo fasi di lavorazione, righe lette da un file ed elaborate, etc.
Non necessariamente tale indicazione di avanzamento è utile od opportuna, tornando al caso di un file di grosse dimensioni, diciamo 1 Gb, elaborato con un buffer da 1 Kb, potrebbe dare decine di aggiornamenti al secondo, in tal caso sarebbe opportuno memorizzare la quantità intera segnalata e solo qualora cambi segnalare, od anche potrebbero essere esose e ridondanti i calcoli necessari allo aggiornamento dell'avanzamento, in tal caso potrebbe essere meglio utilizzare una indicazione generica, p.e. posizionando un singolo carattere "#" che scorra avanti ed indietro sino alla fine della elaborazione, senza alcuna quantificazione e solo per indicare che c'è una attività in corso.

In ogni caso, tal genere di segnali sono da effettuarsi quando una elaborazione richieda effettivamente una significativa quantità di tempo, non vale la pena di implementarli per cose rapide come una copia locale di file (troppo rapida normalmente), mentre potrebbe essere utile in caso di download, e, comunque sarebbe indispensabile poter "quantificare" per dare indicazioni percentuali
... altrimenti è opportuno ricorrere ad indicazioni per "lavori in corso" ;)

[Edit] Vedo ora lo "Edit" da Te inserito mentre stavo rispondendo, guarda che lo sleep di 2 secondi è una istruzione di attesa presente solo per consentirti di visualizzare il refresh della stringa, altrimenti Ti apparirebbe solo la scritta finale, non dovrebbe essere presente in script applicativi (salvo casi particolari) perché ostacolerebbe le elaborazioni, ritardandole.
Lo script di esempio che Ti ho fatto era mera indicazione sul come "fare una barra", cosa da Te richiesta, non ha nulla a che vedere con l'operazione di copia che cerchi di re-indirizzargli.
Fatti non foste a viver come bruti ...
Avatar utente
Pehua
Prode Principiante
Messaggi: 241
Iscrizione: martedì 19 aprile 2022, 9:02
Desktop: Ubuntu
Distribuzione: Ubuntu 22.04.4 LTS
Sesso: Maschile

Re: Progress bar output comando

Messaggio da Pehua »

nuzzopippo ha scritto:
mercoledì 22 febbraio 2023, 7:37
Pehua ha scritto:
mercoledì 22 febbraio 2023, 6:48
1 Parlando del tuo codice, come avanza la $barra#
È piuttosto semplice, alla riga 3 definisco una variabile "barra" che altro non è che una stringa vuota

Codice: Seleziona tutto

barra=""
all'interno del ciclo for aggiungo un carattere "#" ridefinendo la variabile "barra" come una stringa che ha il precedente contenuto della stessa variabile ($barra) ed un carattere "#", L'ISTRUZIONE È

Codice: Seleziona tutto

barra="$barra#"
Pehua ha scritto:
mercoledì 22 febbraio 2023, 6:48
2 In generale, anche di esempi trovati con ciclo while etc, ma con counter a numeri da uno a dieci o simili, come applicarli all' output di un comando qualsiasi che richiede "tempo", una copia di un file grande per esempio o qualcosa del genere.
Non esiste una regola generale, bisogna valutare caso per caso cosa è utile mostrare e se mostrare, non sempre è semplice farlo, non sempre è il caso di farlo, di norma, per utilizzare canonicamente una "barra di avanzamento" bisogna conoscere quantitativamente il "peso" da raggiungere e la quantità realizzata ad ogni passaggio, nel caso di un file di grandi dimensioni, p.e., la dimensione in bytes del file e la quantità di bytes elaborati ad ogni singola passata, quindi calcolarsi la percentuale elaborata ad ogni singolo passaggio con la solita formula x= (quantità elaborata / quantità totale) * 100, quindi costruire una stringa contenente il segnale di tale avanzamento, tipo un carattere "#" ogni 5 punti, ad esempio, sarebbero 20 caratteri alla percentuale 100.
Ovviamente, tale considerazione vale per qualsiasi frangente, tipo fasi di lavorazione, righe lette da un file ed elaborate, etc.
Non necessariamente tale indicazione di avanzamento è utile od opportuna, tornando al caso di un file di grosse dimensioni, diciamo 1 Gb, elaborato con un buffer da 1 Kb, potrebbe dare decine di aggiornamenti al secondo, in tal caso sarebbe opportuno memorizzare la quantità intera segnalata e solo qualora cambi segnalare, od anche potrebbero essere esose e ridondanti i calcoli necessari allo aggiornamento dell'avanzamento, in tal caso potrebbe essere meglio utilizzare una indicazione generica, p.e. posizionando un singolo carattere "#" che scorra avanti ed indietro sino alla fine della elaborazione, senza alcuna quantificazione e solo per indicare che c'è una attività in corso.

In ogni caso, tal genere di segnali sono da effettuarsi quando una elaborazione richieda effettivamente una significativa quantità di tempo, non vale la pena di implementarli per cose rapide come una copia locale di file (troppo rapida normalmente), mentre potrebbe essere utile in caso di download, e, comunque sarebbe indispensabile poter "quantificare" per dare indicazioni percentuali
... altrimenti è opportuno ricorrere ad indicazioni per "lavori in corso" ;)
Ciao, concordo che non sempre è buono avere un out che copra quello di default, es apt update o full-upgrade è importante leggere ciò che dice l' output e ok.

Nella copia di un file è solo uno sfizio, sempre cercando in rete ho trovato il comando pv ma non riesco a farlo funzionare a mio piacimento.

Ho trovato un codice che usa il pid del comando (se ho capito bene) per vedere finche finisce, una barra di avanzamento:

Codice: Seleziona tutto

cp ~/Video/video.mp4 ~/Scrivania 2>/dev/null &

pid=$! # Process Id of the previous running command

spin='\*|*/'

i=0
while kill -0 $pid 2>/dev/null
do
  i=$(( (i+1) %4 ))
  printf "\r${spin:$i:1}"
  sleep .1
done
echo
echo "The End!"
Ho personalizzato lo $spin ed ho cercato di aggiustarlo al tuo codice che ha un output migliore, come posso integrare lo spin (che comunque è piacevole, mostrando anche la barra e la percentuale come nel tuo codice?

es: spin percentuale barra#

Ripeto, ho cercato di fare dei due codici uno ma non sono in grado :D

Grazie mille comunque.
Al di la delle impostazioni culturali :birra:
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1627
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: Progress bar output comando

Messaggio da nuzzopippo »

Ripeto, ho cercato di fare dei due codici uno ma non sono in grado :D
Non è in grado nessuno di combinare una cosa che cicla tra 4 caratteri con un qualcosa che deve fare un avanzamento percentuale

per quanto riguarda "pv" dai un

Codice: Seleziona tutto

sudo apt install pv
e poi un

Codice: Seleziona tutto

pv file_origune > file_destinazione
... ma rimarrai deluso, questa sessione di prova

Codice: Seleziona tutto

NzP:~$ pv ~/Video/I_13_spettri.avi > ~/tmp/13_spettri.avi
 716MiB 0:00:00 [1,30GiB/s] [================================>] 100%            
NzP:~$ 
è stata praticamente istantanea

Analogamente sarebbe praticamente istantanea una copia con avanzamento percentuale, dove, però avresti un po' di problemi a calcolarti, con bash, la percentuale di lavoro effettuata, esistono varie possibilità per fare cose del genere ma di norma si appoggiano su implementazioni specifiche, su due piedi potrei fartela in altri linguaggi, tipo python, per bash dovrei rispolverarmi parecchio le idee per poter dire qualcosa in merito, vedremo.
Fatti non foste a viver come bruti ...
Avatar utente
Pehua
Prode Principiante
Messaggi: 241
Iscrizione: martedì 19 aprile 2022, 9:02
Desktop: Ubuntu
Distribuzione: Ubuntu 22.04.4 LTS
Sesso: Maschile

Re: Progress bar output comando

Messaggio da Pehua »

nuzzopippo ha scritto:
mercoledì 22 febbraio 2023, 8:51
Ripeto, ho cercato di fare dei due codici uno ma non sono in grado :D
Non è in grado nessuno di combinare una cosa che cicla tra 4 caratteri con un qualcosa che deve fare un avanzamento percentuale

per quanto riguarda "pv" dai un

Codice: Seleziona tutto

sudo apt install pv
e poi un

Codice: Seleziona tutto

pv file_origune > file_destinazione
... ma rimarrai deluso, questa sessione di prova

Codice: Seleziona tutto

NzP:~$ pv ~/Video/I_13_spettri.avi > ~/tmp/13_spettri.avi
 716MiB 0:00:00 [1,30GiB/s] [================================>] 100%            
NzP:~$ 
è stata praticamente istantanea

Analogamente sarebbe praticamente istantanea una copia con avanzamento percentuale, dove, però avresti un po' di problemi a calcolarti, con bash, la percentuale di lavoro effettuata, esistono varie possibilità per fare cose del genere ma di norma si appoggiano su implementazioni specifiche, su due piedi potrei fartela in altri linguaggi, tipo python, per bash dovrei rispolverarmi parecchio le idee per poter dire qualcosa in merito, vedremo.
Intanto grazie ancora e non c'è bisogno di un codice in altri linguaggi e la cosa non merita cotanto disturbo.

Pv l' avevo provato cosi ma non mi piace:

Codice: Seleziona tutto

cp "video.mp4" ~/Scrivania/ | pv -p -s 53091k
Questo è sicuramente meglio:

Codice: Seleziona tutto

pv ~/Video/I_13_spettri.avi > ~/tmp/13_spettri.avi
La cosa per me è puramente di curiosità, ho scoperto anche yad o zenity che hanno un linguaggio talmente semplice da essere alla mia portata.

Per l' integrazione del tuo codice non sapevo potesse essere cosi tanto difficile, se riuscirò allora ci metterò giusto una barra progressiva (Sempre che si possa fare e ci riesca) senza percentuale, altrimenti me lo tengo cosi com'è senza pretese.

La cosa del pid mi è piaciuta però, è una buona idea, io avevo pensato in modo simile tipo, finche quel comando è attivo, mostra la barra che avanza... Ma non ho conoscenze per farlo, poi ho incontrato quel codice ed ho capito che l' idea non era male e sicuramente la posso usare come base per costruire qualcosa che mi aggradi di più.

Metto risolto ma se ci sono altre idee "semplici" è benvenuto chiunque le posti.

Buona giornata @nuzzopippo :birra:

EDIT
Ho trovato un mix che mi va benissimo:

Codice: Seleziona tutto

barra=""

cp ~/Video/video.mp4 ~/Scrivania 2>/dev/null &

pid=$! # Process Id of the previous running command

spin='\*|*/'

i=0
while kill -0 $pid 2>/dev/null
do
  i=$(( (i+1) %4 ))
  printf "\r${spin:$i:1}"
  barra="$barra#"
  echo -ne "$barra\r"
  printf "\r"  # Se commento questa riga i # riempiono tutto il terminale finche non finisce, mi piace di piu cosi
  sleep .1
done
echo
echo "The End!"
Al di la delle impostazioni culturali :birra:
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 17 ospiti