Aller au contenu principal

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/www plutôt qu'un champ vide.
  • --passwordbox "texte" h l : identique, mais masque la saisie. Avec dialog (contrairement à whiptail), rien ne s'affiche du tout par défaut ; l'option --insecure fait apparaître des astérisques, ce qui rassure l'utilisateur sur le fait que sa frappe est bien prise en compte.
attention

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 :

  1. $( ... ) : 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. 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 $(...).
  3. 1>/dev/tty : « la sortie standard (fd 1) repart maintenant vers le terminal » → l'interface graphique redevient visible à l'écran.
attention

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; }
info

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
astuce

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


Sur quelle sortie dialog écrit-il le texte saisi par l'utilisateur ?


À quoi sert 1>/dev/tty dans var=$(dialog --inputbox ... 2>&1 1>/dev/tty) ?


Que contient la variable si l'utilisateur appuie sur Annuler ?


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


Bonne pratique - Proposer 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


Bonne pratique - Toujours la même formule de capture

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


Bonne pratique - Sortir proprement

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


Bonne pratique - Ne jamais faire confiance à une saisie

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.

📌 Une solution