Lors de l'écriture de scripts dans bash ou tout autre shell dans * NIX, lors de l'exécution d'une commande qui prendra plus de quelques secondes, une barre de progression est nécessaire.
Par exemple, copier un gros fichier, ouvrir un gros fichier tar.
Quelles méthodes recommandez-vous pour ajouter des barres de progression aux scripts shell?
Réponses:
Vous pouvez implémenter cela en écrasant une ligne. Permet
\r
de revenir au début de la ligne sans écrire\n
sur le terminal.Écrivez
\n
quand vous avez terminé pour faire avancer la ligne.Utilisez
echo -ne
pour:\n
et\r
.Voici une démo:
Dans un commentaire ci-dessous, puk mentionne que cela "échoue" si vous commencez par une longue ligne et que vous souhaitez ensuite écrire une ligne courte: dans ce cas, vous devrez écraser la longueur de la longue ligne (par exemple, avec des espaces).
la source
printf
au lieu deecho
.printf "#### (50%%)\r"
:, cela ne fonctionnerait pas avec des guillemets simples et le signe de pourcentage doit être échappé.Vous pouvez également être intéressé par la façon de faire un spinner :
Puis-je faire un spinner dans Bash?
la source
while :;do for s in / - \\ \|; do printf "\r$s";sleep .1;done;done
(*:sleep
peut nécessiter des points plutôt que des décimales)some_work ...
ligne ci-dessus; une discussion plus détaillée qui s'appuie sur cette réponse utile et le commentaire utile d'Adam Katz - en mettant l'accent sur la conformité POSIX - peut être trouvée ici .\b
plutôt que\r
, car il ne fonctionnera autrement qu'au tout début d'une ligne:while :; do for c in / - \\ \|; do printf '%s\b' "$c"; sleep 1; done; done
- ou, si vous affichez le curseur derrière le spinner est indésirable:printf ' ' && while :; do for c in / - \\ \|; do printf '\b%s' "$c"; sleep 1; done; done
job=$!
) puis exécuterwhile kill -0 $job 2>/dev/null;do …
, par exemple:sleep 15 & job=$!; while kill -0 $job 2>/dev/null; do for s in / - \\ \|; do printf "\r$s"; sleep .1; done; done
Certains articles ont montré comment afficher la progression de la commande. Pour le calculer, vous devrez voir combien vous avez progressé. Sur les systèmes BSD, certaines commandes, telles que dd (1), acceptent un
SIGINFO
signal et signalent leur progression. Sur les systèmes Linux, certaines commandes répondent de la même manièreSIGUSR1
. Si cette fonctionnalité est disponible, vous pouvez diriger votre entrée viadd
pour surveiller le nombre d'octets traités.Vous pouvez également utiliser
lsof
pour obtenir le décalage du pointeur de lecture du fichier et ainsi calculer la progression. J'ai écrit une commande, nommée pmonitor , qui affiche la progression du traitement d'un processus ou d'un fichier spécifié. Avec lui, vous pouvez faire des choses, comme les suivantes.Une version antérieure des scripts shell Linux et FreeBSD apparaît sur mon blog .
la source
awk
est en jeu!J'ai une fonction de barre de progression facile que j'ai écrite l'autre jour:
Ou accrochez-le,
https://github.com/fearside/ProgressBar/
la source
printf "\rProgress : [${_fill// /▇}${_empty// / }] ${_progress}%%"
utilisez la commande linux pv:
http://linux.die.net/man/1/pv
il ne connaît pas la taille s'il est au milieu du flux, mais il donne une vitesse et un total et à partir de là, vous pouvez déterminer combien de temps cela devrait prendre et obtenir des commentaires afin que vous sachiez qu'il n'a pas bloqué.
la source
Je cherchais quelque chose de plus sexy que la réponse choisie, tout comme mon propre script.
Aperçu
La source
Je l'ai mis sur github
progress-bar.sh
Usage
la source
progress-bar 100
GNU tar a une option utile qui donne la fonctionnalité d'une simple barre de progression.
(...) Une autre action de point de contrôle disponible est «point» (ou «.»). Il demande à tar d'imprimer un seul point sur le flux de liste standard, par exemple:
Le même effet peut être obtenu par:
la source
--checkpoint=.10
. Cela fonctionne également très bien lors de l'extraction avectar -xz
.Une méthode plus simple qui fonctionne sur mon système à l'aide de l'utilitaire pipeview (pv).
la source
Je n'ai rien vu de similaire et toutes les fonctions personnalisées semblent se concentrer uniquement sur le rendu, alors ... ma solution très simple conforme POSIX ci-dessous avec des explications étape par étape car cette question n'est pas triviale.
TL; DR
Le rendu de la barre de progression est très simple. L'estimation de la quantité à rendre doit être différente. Voici comment rendre (animer) la barre de progression - vous pouvez copier et coller cet exemple dans un fichier et l'exécuter:
{1..20}
- valeurs de 1 à 20echo -n
- imprimer sans nouvelle ligne à la finecho -e
- interpréter des caractères spéciaux lors de l'impression"\r"
- retour chariot, un caractère spécial pour revenir au début de la ligneVous pouvez lui faire rendre n'importe quel contenu à n'importe quelle vitesse, donc cette méthode est très universelle, par exemple souvent utilisée pour la visualisation de "piratage" dans des films stupides, sans blague.
Réponse complète
Le gros du problème est de savoir comment déterminer la
$i
valeur, c'est-à-dire quelle proportion de la barre de progression afficher. Dans l'exemple ci-dessus, je l'ai simplement laissé incrémenter enfor
boucle pour illustrer le principe, mais une application réelle utiliserait une boucle infinie et calculerait la$i
variable à chaque itération. Pour effectuer ce calcul, il a besoin des ingrédients suivants:Dans le cas où
cp
il a besoin de la taille d'un fichier source et de la taille du fichier cible:stat
- vérifier les statistiques des fichiers-c
- retourne une valeur formatée%s
- taille totaleDans le cas d'opérations comme le décompression de fichiers, le calcul de la taille de la source est légèrement plus difficile mais toujours aussi simple que d'obtenir la taille d'un fichier non compressé:
gzip -l
- afficher des informations sur l'archive ziptail -n1
- travailler avec 1 ligne à partir du bastr -s ' '
- traduire plusieurs espaces en un (les presser)cut -d' ' -f3
- couper la 3e colonne délimitée par des espacesVoici la chair du problème, cependant. Cette solution est de moins en moins générale. Tous les calculs de la progression réelle sont étroitement liés au domaine que vous essayez de visualiser, est-ce une opération sur un seul fichier, un compte à rebours, un nombre croissant de fichiers dans un répertoire, une opération sur plusieurs fichiers, etc., par conséquent, il ne peut pas être réutilisé. La seule partie réutilisable est le rendu de la barre de progression. Pour le réutiliser, vous devez l'abstraire et l'enregistrer dans un fichier (par exemple
/usr/lib/progress_bar.sh
), puis définir des fonctions qui calculent les valeurs d'entrée spécifiques à votre domaine. Voici à quoi pourrait ressembler un code généralisé (j'ai aussi fait la$BAR
dynamique parce que les gens le demandaient, le reste devrait être clair maintenant):printf
- un intégré pour imprimer des trucs dans un format donnéprintf '%50s'
- n'imprimez rien, remplissez-le de 50 espacestr ' ' '#'
- traduire chaque espace en signe de hachageEt voici comment vous l'utiliseriez:
Évidemment, il peut être enveloppé dans une fonction, réécrit pour fonctionner avec des flux canalisés, réécrit dans une autre langue, quel que soit votre poison.
la source
Je voudrais également apporter ma contribution propre barre de progression
Il atteint la précision des sous-caractères en utilisant des blocs Half Unicode
Le code est inclus
la source
Barre de progression de style APT (ne casse pas la sortie normale)
EDIT: Pour une version mise à jour, consultez ma page github
Je n'étais pas satisfait des réponses à cette question. Ce que je cherchais personnellement, c'était une barre de progression sophistiquée, comme le voit APT.
J'ai regardé le code source C pour APT et j'ai décidé d'écrire mon propre équivalent pour bash.
Cette barre de progression restera bien en bas du terminal et n'interférera pas avec les sorties envoyées au terminal.
Veuillez noter que la barre est actuellement fixée à 100 caractères de large. Si vous voulez l'adapter à la taille du terminal, cela est également assez facile à réaliser (la version mise à jour sur ma page github gère bien cela).
Je posterai mon script ici. Exemple d'utilisation:
Le script (je recommande fortement la version sur mon github à la place):
la source
Cela vous permet de visualiser qu'une commande est toujours en cours d'exécution:
Cela va créer une boucle while infinie qui s'exécute en arrière-plan et fait écho à un "." chaque seconde. Cela s'affichera
.
dans le shell. Exécutez latar
commande ou n'importe quelle commande de votre choix. Lorsque cette commande a terminé son exécution, supprimez le dernier travail exécuté en arrière-plan - qui est la boucle while infinie .la source
Voici à quoi cela pourrait ressembler
Téléchargement d'un fichier
En attente d'un travail pour terminer
Fonction simple qui l'implémente
Vous pouvez simplement le copier-coller dans votre script. Il ne nécessite rien d'autre pour fonctionner.
Exemple d'utilisation
Ici, nous téléchargeons un fichier et redessinons la barre de progression à chaque itération. Peu importe le travail réellement effectué tant que nous pouvons obtenir 2 valeurs: la valeur maximale et la valeur actuelle.
Dans l'exemple ci-dessous, la valeur maximale est
file_size
et la valeur actuelle est fournie par une fonction et est appeléeuploaded_bytes
.la source
La plupart des commandes Unix ne vous donneront pas le type de rétroaction directe à partir de laquelle vous pouvez le faire. Certains vous donneront une sortie sur stdout ou stderr que vous pouvez utiliser.
Pour quelque chose comme tar, vous pouvez utiliser le commutateur -v et diriger la sortie vers un programme qui met à jour une petite animation pour chaque ligne qu'il lit. Au fur et à mesure que tar écrit une liste de fichiers, le programme peut mettre à jour l'animation. Pour terminer un pourcentage, vous devez connaître le nombre de fichiers et compter les lignes.
cp ne donne pas ce genre de sortie pour autant que je sache. Pour surveiller la progression de cp, vous devez surveiller les fichiers source et de destination et surveiller la taille de la destination. Vous pouvez écrire un petit programme c en utilisant l' appel système stat (2) pour obtenir la taille du fichier. Cela permettrait de lire la taille de la source, puis d'interroger le fichier de destination et de mettre à jour une barre% complète en fonction de la taille du fichier écrit à ce jour.
la source
Ma solution affiche le pourcentage de l'archive tar qui est actuellement non compressé et écrit. Je l'utilise lors de l'écriture d'images de système de fichiers racine de 2 Go. Vous avez vraiment besoin d'une barre de progression pour ces choses. Ce que je fais c'est utiliser
gzip --list
pour obtenir la taille totale non compressée de l'archive tar. À partir de cela, je calcule le facteur de blocage nécessaire pour diviser le fichier en 100 parties. Enfin, j'imprime un message de point de contrôle pour chaque bloc. Pour un fichier de 2 Go, cela donne environ 10 Mo de bloc. Si c'est trop grand, vous pouvez diviser le BLOCKING_FACTOR par 10 ou 100, mais il est alors plus difficile d'imprimer une jolie sortie en termes de pourcentage.En supposant que vous utilisez Bash, vous pouvez utiliser la fonction shell suivante
la source
Tout d'abord, la barre n'est pas le seul indicateur de progression de tuyau. L'autre (peut-être encore plus connu) est le pv (pipe viewer).
Deuxièmement, bar et pv peuvent être utilisés par exemple comme ceci:
ou même:
une astuce utile si vous voulez utiliser bar et pv dans des commandes qui fonctionnent avec des fichiers donnés en arguments, comme par exemple copier file1 file2, est d'utiliser la substitution de processus :
La substitution de processus est une chose magique qui crée des fichiers de tuyaux fifo temporaires / dev / fd / et connecte stdout à partir du processus exécuté (entre parenthèses) via ce tuyau et la copie le voit comme un fichier ordinaire (à une exception près, il ne peut le lire que vers l'avant).
Mise à jour:
La commande bar elle-même permet également la copie. Après la barre d'homme:
Mais la substitution de processus est à mon avis une manière plus générique de le faire. Un il utilise le programme cp lui-même.
la source
Je préfère utiliser le dialogue avec le paramètre --gauge . Est utilisé très souvent dans les installations de packages .deb et d'autres éléments de configuration de base de nombreuses distributions. Vous n'avez donc pas besoin de réinventer la roue ... encore
Mettez simplement une valeur int de 1 à 100 @stdin. Un exemple basique et idiot:
J'ai ce fichier / bin / Wait (avec chmod u + x perms) à des fins de cuisine: P
Je peux donc mettre:
Wait "34 min" "warm up the oven"
ou
Wait "dec 31" "happy new year"
la source
pour moi le plus facile à utiliser et le plus beau à ce jour est la commande
pv
oubar
comme un gars a déjà écritpar exemple: besoin de faire une sauvegarde de tout le lecteur avec
dd
normalement vous utilisez
dd if="$input_drive_path" of="$output_file_path"
avec
pv
vous pouvez le faire comme ceci:dd if="$input_drive_path" | pv | dd of="$output_file_path"
et les progrès vont directement à
STDOUT
ceci:une fois le résumé terminé,
la source
pv
oubar
pour visualiser la progression de différents processus, par exemple le compte à rebours du minuteur, la position dans un fichier texte, l'installation de votre application, la configuration de l'exécution, etc.?De nombreuses réponses décrivent l'écriture de vos propres commandes pour l'impression
'\r' + $some_sort_of_progress_msg
. Le problème est parfois que l'impression de centaines de ces mises à jour par seconde ralentira le processus.Cependant, si l'un de vos processus produit une sortie (par exemple,
7z a -r newZipFile myFolder
il affichera chaque nom de fichier au fur et à mesure qu'il le compresse), une solution plus simple, rapide, indolore et personnalisable existe.Installez le module python
tqdm
.Aide:
tqdm -h
. Un exemple utilisant plus d'options:En prime, vous pouvez également utiliser
tqdm
pour envelopper les itérables dans du code python.https://github.com/tqdm/tqdm/blob/master/README.rst#module
la source
tqdm
STDOUT àwc -l
travers un tuyau. Vous voulez probablement y échapper.tqdm
affichera la progressionSTDERR
tout en redirigeant son entréeSTDIN
versSTDOUT
. Dans ce cas,wc -l
devrait recevoir la même entrée que si elletqdm
n'était pas incluse.Sur la base du travail d'Edouard Lopez, j'ai créé une barre de progression qui s'adapte à la taille de l'écran, quelle qu'elle soit. Vérifiez-le.
Il est également publié sur Git Hub .
Prendre plaisir
la source
https://github.com/extensionsapp/progre.sh
Créez une progression de 40%:
progreSh 40
la source
Cela ne s'applique qu'à l'aide de gnome zenity. Zenity fournit une excellente interface native pour les scripts bash: https://help.gnome.org/users/zenity/stable/
Exemple de barre de progression Zenity:
la source
J'ai utilisé une réponse de Création d'une chaîne de caractères répétés dans le script shell pour la répétition de caractères. J'ai deux versions bash relativement petites pour les scripts qui doivent afficher la barre de progression (par exemple, une boucle qui traverse de nombreux fichiers, mais pas utile pour les gros fichiers tar ou les opérations de copie). La plus rapide se compose de deux fonctions, l'une pour préparer les chaînes pour l'affichage des barres:
et une pour afficher une barre de progression:
Il pourrait être utilisé comme:
ce qui signifie préparer des chaînes pour la barre avec 50 caractères "#", et après cela:
affichera le nombre de caractères "#" qui correspond au rapport 35/80:
N'oubliez pas que la fonction affiche la barre sur la même ligne encore et encore jusqu'à ce que vous (ou un autre programme) imprimiez une nouvelle ligne. Si vous mettez -1 comme premier paramètre, la barre sera effacée:
La version plus lente est tout en une fonction:
et il peut être utilisé comme (le même exemple que ci-dessus):
Si vous avez besoin de la barre de progression sur stderr, ajoutez simplement
>&2
à la fin de chaque commande printf.la source
Pour indiquer la progression de l'activité, essayez les commandes suivantes:
OU
OU
OU
On peut utiliser des drapeaux / variables à l'intérieur de la boucle while pour vérifier et afficher la valeur / l'étendue de la progression.
la source
En utilisant les suggestions listées ci-dessus, j'ai décidé d'implémenter ma propre barre de progression.
la source
percent_none="$(( 100 - "$percent_done" ))"
pourpercent_none="$(( 100 - $percent_done))"
J'ai fait une version pure shell pour un système embarqué en profitant de:
/ usr / bin / dd la fonction de gestion du signal SIGUSR1.
Fondamentalement, si vous envoyez un 'kill SIGUSR1 $ (pid_of_running_dd_process)', il affichera un résumé de la vitesse de débit et du montant transféré.
en arrière-plan dd puis en l'interrogeant régulièrement pour les mises à jour, et en générant des ticks de hachage comme les clients ftp de la vieille école le faisaient auparavant.
Utilisation de / dev / stdout comme destination pour des programmes non compatibles avec stdout comme scp
Le résultat final vous permet d'effectuer n'importe quelle opération de transfert de fichier et d'obtenir une mise à jour de progression qui ressemble à une sortie FTP de hachage à l'ancienne où vous obtiendrez simplement une marque de hachage pour chaque X octets.
Ce n'est pas du code de qualité de production, mais vous avez l'idée. Je pense que c'est mignon.
Pour ce que ça vaut, le nombre d'octets réel peut ne pas être reflété correctement dans le nombre de hachages - vous pouvez en avoir un de plus ou moins selon les problèmes d'arrondi. Ne l'utilisez pas dans le cadre d'un script de test, c'est juste un régal pour les yeux. Et, oui, je suis conscient que c'est terriblement inefficace - c'est un script shell et je ne m'en excuse pas.
Exemples avec wget, scp et tftp fournis à la fin. Cela devrait fonctionner avec tout ce qui a émis des données. Assurez-vous d'utiliser / dev / stdout pour les programmes qui ne sont pas compatibles avec stdout.
Exemples:
la source
pidof dd
c'est effrayant.$!
partirdd
et attendre[[ -e /proc/${DD_PID} ]]
.Dans le cas où vous devez afficher une barre de progression temporelle (en connaissant à l'avance l'heure d'affichage), vous pouvez utiliser Python comme suit:
Ensuite, en supposant que vous avez enregistré le script Python sous
progressbar.py
, il est possible d'afficher la barre de progression de votre script bash en exécutant la commande suivante:Il afficherait une barre de progression des
50
caractères de taille et "en cours d'exécution" pendant10
quelques secondes.la source
J'ai construit sur la réponse fournie par fearside
Cela se connecte à une base de données Oracle pour récupérer la progression d'une restauration RMAN.
la source
pourrait créer une fonction qui dessine ceci sur une échelle disons 1-10 pour le nombre de barres:
la source
production:
note: si au lieu de 255 vous mettez 1 vous surveillerez la norme en ... avec 2 la norme en sortie (mais vous devez modifier la source pour définir "tot" à la taille du fichier de sortie projeté)
la source