Récupérer la saisie de l'utilisateur
Notions théoriques
Après avoir informé l'utilisateur (--msgbox) et lui avoir demandé une confirmation (--yesno), l'étape suivante consiste à lui demander de saisir une information : un dossier, un nom, un mot de passe.
Les widgets de saisie
--inputbox "texte" h l [valeur_par_defaut]: affiche un champ de saisie texte. Le 4ᵉ paramètre, optionnel, pré-remplit le champ — pratique pour proposer/var/wwwplutôt qu'un champ vide.--passwordbox "texte" h l: identique, mais masque la saisie. Avecdialog(contrairement àwhiptail), rien ne s'affiche du tout par défaut ; l'option--insecurefait apparaître des astérisques, ce qui rassure l'utilisateur sur le fait que sa frappe est bien prise en compte.
Ne réaffichez jamais un mot de passe saisi dans une --msgbox, et ne le passez jamais en argument d'une commande : un argument de commande est visible en clair par tous les utilisateurs du système via ps aux.
Le point délicat : récupérer la saisie dans une variable
Avec echo et read, on écrit simplement read -p "..." variable. Avec dialog/whiptail, ce n'est pas aussi direct, et c'est le point technique le plus important de cette séance.
dialog et whiptail dessinent leur interface sur la sortie standard (c'est ce que vous voyez dans le terminal), mais écrivent le résultat saisi sur la sortie d'erreur (rappel de la séance Bonnes pratiques du niveau 1, qui a introduit >&2).
Si vous essayez naïvement :
dossier=$(dialog --inputbox "Dossier ?" 8 50)
la variable dossier reste vide : le $(...) capture uniquement la sortie standard, c'est-à-dire le dessin de la boîte, pas la valeur saisie.
La formule canonique
dossier=$("$DIALOG" --inputbox "Dossier à sauvegarder ?" 8 50 "/etc" 2>&1 1>/dev/tty)
Cette ligne se lit dans l'ordre, de gauche à droite :
$( ... ): la substitution de commande capture ce que la commande écrit sur sa sortie standard (fd 1) — à cet instant, fd 1 est déjà redirigé vers ce tuyau invisible.2>&1: « la sortie d'erreur (fd 2) va désormais là où va la sortie standard actuellement » → le résultat saisi, écrit sur fd 2, part donc dans le tuyau capturé par$(...).1>/dev/tty: « la sortie standard (fd 1) repart maintenant vers le terminal » → l'interface graphique redevient visible à l'écran.
L'ordre de ces deux redirections est essentiel et ne peut pas être inversé. Écrire 1>/dev/tty 2>&1 enverrait tout vers le terminal, et la variable resterait vide : au moment où 2>&1 s'exécute, fd 1 pointerait déjà vers /dev/tty et non plus vers le tuyau.
Des alternatives, selon la version installée
--output-fd 1(versions récentes) :dossier=$("$DIALOG" --output-fd 1 --inputbox ... 2>/dev/null)— l'outil écrit alors directement le résultat sur fd 1.dialog --stdout ...: raccourci propre àdialog, absent de whiptail, donc moins portable dans un script qui doit fonctionner avec les deux.- Un descripteur temporaire :
exec 3>&1; dossier=$("$DIALOG" --inputbox ... 2>&1 1>&3); exec 3>&-.
Pour un script destiné à fonctionner avec dialog et whiptail, la formule 2>&1 1>/dev/tty reste la plus portable et la plus répandue : c'est celle que nous utiliserons dans tout ce sous-cours.
Toujours vérifier le code de retour avant d'utiliser la saisie
Si l'utilisateur annule (Cancel ou Échap), la variable reste vide, mais le script continue quand même si l'on ne vérifie rien :
dossier=$("$DIALOG" --inputbox "Dossier ?" 8 50 2>&1 1>/dev/tty) || { clear; exit 1; }
Le niveau 1 a introduit set -u, qui protège contre une variable jamais définie. Ici, dossier est bien définie, simplement vide — set -u ne détecte donc pas ce cas, d'où l'importance de tester explicitement le code de retour.
Valider la saisie
Une fois récupérée, la saisie doit être vérifiée comme n'importe quelle entrée utilisateur (rappel de la séance Conditions) :
if [ -z "$dossier" ]; then
"$DIALOG" --msgbox "Aucun dossier saisi." 8 40
fi
if [ ! -d "$dossier" ]; then
"$DIALOG" --msgbox "Ce dossier n'existe pas." 8 40
fi
On peut combiner cela à une boucle while (rappel de la séance Boucles) pour redemander tant que la saisie n'est pas valide. Et comme toujours, "$dossier" doit rester entre guillemets : un chemin saisi peut contenir des espaces.
Exemple pratique
#!/bin/bash
# Script : saisie_tui.sh
# Rôle : demander un nom d'utilisateur et un mot de passe via dialog/whiptail
# Auteur : Votre nom
set -eu
DIALOG="whiptail"
nom=$("$DIALOG" --inputbox "Nom d'utilisateur ?" 8 50 "$USER" 2>&1 1>/dev/tty) || { clear; exit 1; }
motdepasse=$("$DIALOG" --passwordbox "Mot de passe ?" 8 50 2>&1 1>/dev/tty) || { clear; exit 1; }
clear
"$DIALOG" --msgbox "Utilisateur : $nom
Mot de passe : ********" 8 50
Notez que le mot de passe n'est jamais réaffiché en clair, même dans la boîte récapitulative finale.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Nous poursuivons sauvegarde_tui.sh : le dossier à sauvegarder n'est plus codé en dur, il est demandé à l'utilisateur.
Étape 1 — Demander le dossier avec une valeur par défaut
Pré-remplir le champ avec une valeur plausible (/etc, le dossier courant...) fait gagner du temps à l'utilisateur et réduit le risque de faute de frappe sur un chemin long.
Étape 2 — Capturer correctement la saisie
Utilisez systématiquement 2>&1 1>/dev/tty pour capturer une saisie dialog/whiptail. En la retapant toujours à l'identique, vous éviterez l'erreur classique d'inversion de l'ordre.
Étape 3 — Gérer le bouton Annuler
Une annulation n'est pas une erreur de programmation : traitez-la explicitement (clear puis exit) plutôt que de laisser le script continuer avec une variable vide.
Étape 4 — Refuser un dossier inexistant et redemander
Une saisie utilisateur, qu'elle vienne de read ou d'un --inputbox, doit toujours être validée avant d'être utilisée dans une commande qui modifie ou lit des fichiers.