Linux - Utiliser une barre de progression dans vos scripts
Ajoutez une barre de progression visuelle à vos scripts Bash sous Linux. Ce guide vous montre comment implémenter facilement une barre de progression pour suivre des jobs concurrents, visualiser l'avancement et améliorer votre interface dans le terminal.
Traduction automatique
Cet article a plus d'un an, mais il a été relu le 30 juillet 2026 — son contenu est toujours exact.
Cet article fait partie de la série Écrire de meilleurs scripts Bash :
- Bash - ASCII art
- Bash - Charger des variables d'environnement depuis un fichier
- Bash - Script pour ajouter des fonctionnalités de log à votre script
- Bash - Afficher sur la console et dans un fichier de log en même temps
- Linux - Comparer deux versions du même script
- Linux - Trier les fonctions dans un script Bash
- Linux - Générer de la documentation à partir de scripts Bash
- Linux - Tirez parti du nombre de CPU dont vous disposez ; lancez des jobs concurrents
- Linux - Utiliser une barre de progression dans vos scripts
- Linux - Scripts Bash - Lancer des tests unitaires avec bats/bats

Cet article de suivi ajoute une barre de progression visuelle aux scripts Bash (dans la continuité de l'article précédent sur les jobs parallèles) à l'aide d'un helper réutilisable progress_bar.sh : sourcez-le, faites passer la sortie de votre boucle dans progress_bar::process "Doing some stuff" 50, et affichez Progress=N depuis l'intérieur de la boucle pour piloter la barre — pratique pour les traitements par lots longs comme des uploads vers une API pilotés par un CSV.
Dans mon article précédent, Linux - Tirez parti du nombre de CPU dont vous disposez ; lancez des jobs concurrents, nous avons vu comment lancer des jobs en parallèle.
La prochaine chose sympa, c'est d'afficher une barre de progression dans votre console. Ça présente plusieurs avantages : une vue claire de ce qui est fait et de ce qui reste à faire, et une interface agréable.
Quand le nombre d'éléments n'est pas connu à l'avance, un compteur en direct est plus adapté ; voyez Compter en continu le nombre de fichiers d'un dossier avec inotifywait. Et pour garder une trace de ce qui s'est passé une fois la barre disparue, Bash - Script pour ajouter des fonctionnalités de log à votre script.
Il y a quelques mois, j'ai trouvé cet article de blog français dans mes flux RSS : https://xieme-art.org/post/bash-avance-barre-de-progression/ et, juste, wow !!!
Amusons-nous avec ça.
Résultat

C'est une simple boucle Bash, sans aucun outil externe, qui pilote une barre de progression en direct dans la console.
Pourquoi ça fonctionne
Un script doit faire trois choses pour obtenir cette barre :
- Sourcer le script
progress_bar.sh(merci à ephase) ; - Lancer la fonction qui fait le vrai travail d'une manière particulière : pas juste
mainmaismain > >(progress_bar::process "Doing some stuff" 50). Le chiffre50doit correspondre au nombre d'itérations de la boucle ; - Depuis l'intérieur de cette fonction, afficher une seule chose dans la console avec
echo:Progress=suivi d'un nombre (de 1 à 50) — c'est le signal que la barre lit pour avancer.
Pas si compliqué, non ?
Créer demo.sh
D'abord, créez un nouveau dossier sur votre disque et déplacez-vous dedans : mkdir /tmp/progress && cd $_.
Ensuite, créez un fichier demo.sh dans ce dossier et copiez/collez le script bash ci-dessous :
#!/bin/bashset -euo pipefail
function demo { echo "Progress=$1" sleep 0.1 return 0}
function main { for i in {1..50}; do demo "$i" done}
source "progress_bar.sh"
main > >(progress_bar::process "Doing some stuff" 50)Ce script bash exécute une boucle qui appelle 50 fois une fonction demo, puis redirige la sortie vers un processus de barre de progression. Le script charge d'abord un fichier externe contenant la logique de la barre de progression, puis lance la fonction main avec la sortie canalisée vers progress_bar::process pour afficher la progression de façon visuelle.
Rendez le script exécutable en lançant chmod +x ./demo.sh.
Créer progress_bar.sh
Voici le contenu à copier/coller dans un fichier appelé progress_bar.sh, créé dans le même dossier que demo.sh.
Créez donc un nouveau fichier sur votre disque dur ; nommez-le progress_bar.sh et copiez/collez le contenu ci-dessous dedans.
#!/usr/bin/env bash
# region - Intro block -----------------------------------------------## Progress bar## ## How to use this script?## Just include this script in your own Bash like this `source progress_bar.sh`## Now, you can use any public functions defined here like `progress_bar::draw``.## ## Example## The example below will just loop for 1 till 50 and the most important part is the "Progress=${i}"# echo statement. The progression of the bar depends on a regex defined in the progress_bar::process() function.## ```bash# function main() {# for i in {1..50}# do# echo "Progress=${i}"# sleep 0.1# done# }## main > >(progress_bar::process "Doing some stuff" 50)# ```## ## Namespace## `progress_bar::`## cspell:ignore endregion## shellcheck disable=SC1090,SC1091## ## Source## The source comes from a French blog post:# https://xieme-art.org/post/bash-avance-barre-de-progression/## shellcheck disable=SC2059## endregion - Intro block --------------------------------------------
# let script exit if an unset variable is used or if a command failsset -o nounsetset -o errexit
# The different bar to display (done)PROGRESS_BAR_CHAR=(█ ▒)
# Show or not the introduction text (f.i. "Doing some stuff")PROGRESS_BAR_DISPLAY_INFO=1
PROGRESS_BAR_DISPLAY_COMP=1
# Display templatePROGRESS_BAR_INFO_TEMPLATE=' %s [ %3d/%3d ] 'PROGRESS_BAR_COMP_TEMPLATE=' %3d%% 'PROGRESS_BAR_TEMPLATE='\033[1m%s%s\033[0m%s%s\r'
# region - private function progress_bar::__change_column_size## ## Description## This function will capture de WINCH signal. That one is fired by Linux when# the size of the window (i.e. the console) is updated so allow us to retrieve the# max. number of columns that can fit in the window.## endregionfunction progress_bar::__change_column_size() { printf >&2 "%${COLUMNS}s" "" printf >&2 "\033[0K\r" COLUMNS=$(tput cols)}
# region - private function progress_bar::__draw## ## Description## Draw the progress bar / progression## endregionfunction progress_bar::__draw() { # function parameters local -r progress=${1?"progress is mandatory"} local -r total=${2?"total elements is mandatory"} local -r info=${3:-"In progress"}
# function local variables local progress_segment local todo_segment local info_segment="" local comp_segment=""
if [[ ${PROGRESS_BAR_DISPLAY_INFO:-1} -eq 1 ]]; then printf -v info_segment "${PROGRESS_BAR_INFO_TEMPLATE}" \ "$info" "$progress" "$total" fi
local -r progress_ratio=$((progress * 100 / total)) if [[ ${PROGRESS_BAR_DISPLAY_COMP:-0} -eq 1 ]]; then printf -v comp_segment "${PROGRESS_BAR_COMP_TEMPLATE}" \ "$progress_ratio" fi
# progress bar construction # calculate each element sizes, bar must fit in ou screen local -r bar_size=$((COLUMNS - ${#info_segment} - ${#comp_segment})) local -r progress_segment_size=$((bar_size * progress_ratio / 100)) local -r todo_segment_size=$((bar_size - progress_segment_size)) printf -v progress_segment "%${progress_segment_size}s" "" printf -v todo_segment "%${todo_segment_size}s" ""
printf >&2 "$PROGRESS_BAR_TEMPLATE" \ "$info_segment" \ "${progress_segment// /${PROGRESS_BAR_CHAR[0]}}" \ "${todo_segment// /${PROGRESS_BAR_CHAR[1]}}" \ "$comp_segment"}
# region - public function progress_bar::process## ## Description## Display a progress bar## ## Example## ```bash# function main() {# for i in {1..50}# do# echo "Progress=${i}"# sleep 0.1# done# }## main > >(progress_bar::process "Doing some stuff" 50)# ```## ## Parameters## * @arg $1 The text to display like "Upload in progress"# * @arg $2 The number of positions in the bar (f.i. if there are 4 rows to proceed, it has to be initialize to 4)## endregionfunction progress_bar::process() { local -r action="${1:-Upload in progress}" local -r max=${2:-100}
# Capture the resize of the window so the progress bar becomes responsive trap progress_bar::__change_column_size WINCH
while read -r line; do # Each line with "Progress=(digit)" will increase the progress bar if [[ $line =~ Progress=([[:digit:]]{1,}) ]]; then progress_bar::__draw "${BASH_REMATCH[1]}" "${max}" "${action}" fi done}
# This script didn't contains executable code; only helpers.sourced=0(return 0 2> /dev/null) && sourced=1 || sourced=0if [ "${sourced}" -eq "0" ]; then printf "\033[1;31m%s\033[0m\n" "ERROR, the $0 script is meant to be sourced. Try 'source $0' and use public functions." >&2 # Write on stderr exit 1fi
return 0Ce script fournit une barre de progression réutilisable pour Bash. Il s'utilise en le chargeant avec source, puis en canalisant la sortie d'une boucle vers la fonction progress_bar::process, qui capte les lignes contenant « Progress=nombre » et affiche une barre mise à jour en temps réel. Le script gère aussi le redimensionnement de la fenêtre de terminal pour adapter la barre de progression.
Place à l'exécution
Retournez simplement dans la console, lancez ./demo.sh et... wow, c'est vraiment chouette — vous obtenez la barre montrée plus haut.
Dans un cas réel, j'ai implémenté cette fonctionnalité dans un script Bash où je dois lire un fichier CSV et, pour chaque enregistrement récupéré dans le fichier, lancer une commande curl pour appeler une API RESTful en POST et uploader un PDF.
Et, quand le script est lancé de manière interactive, la sortie à l'écran est vraiment pratique et terriblement efficace.
Bien sûr, j'utilise aussi un fichier de log où je redirige un maximum d'informations.
Cet article fait partie de la série Écrire de meilleurs scripts Bash :
- Bash - ASCII art
- Bash - Charger des variables d'environnement depuis un fichier
- Bash - Script pour ajouter des fonctionnalités de log à votre script
- Bash - Afficher sur la console et dans un fichier de log en même temps
- Linux - Comparer deux versions du même script
- Linux - Trier les fonctions dans un script Bash
- Linux - Générer de la documentation à partir de scripts Bash
- Linux - Tirez parti du nombre de CPU dont vous disposez ; lancez des jobs concurrents
- Linux - Utiliser une barre de progression dans vos scripts
- Linux - Scripts Bash - Lancer des tests unitaires avec bats/bats
Chargement des commentaires…





