342 votes

Comment exécuter une commande dans bash encore et encore jusqu'à ce qu'elle réussisse ?

J'ai un script et je veux demander certaines informations à l'utilisateur, mais le script ne peut pas continuer tant que l'utilisateur ne remplit pas ces informations. Ce qui suit est ma tentative de mettre une commande dans une boucle pour réaliser cela, mais cela ne fonctionne pas pour une raison quelconque :

echo "Please change password"
while passwd
do
    echo "Try again"
done

J'ai essayé de nombreuses variantes de la boucle while :

while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more

Mais je n'arrive pas à le faire fonctionner.

548voto

Erik Points 38942
until passwd
do
  echo "Try again"
done

ou

while ! passwd
do
  echo "Try again"
done

32 votes

Difficile d'en sortir par Ctrl-C.

0 votes

Si vous pensez avoir besoin d'annuler cette opération, ouvrez simplement une nouvelle instance de votre shell (par exemple, tapez "bash") et, lorsque vous voulez l'annuler, allez dans une autre fenêtre de terminal et tuez le processus bash nouvellement créé.

83 votes

C'est facile d'en sortir avec Ctr-C : until passwd; do echo "Try again"; sleep 2; done - tout ce que vous avez à faire est d'appuyer sur Ctr-C juste après (dans les deux secondes données) la echo a fait son travail.

122voto

duckworthd Points 1830

Pour approfondir la réponse de @Marc B,

$ passwd
$ while [ $? -ne 0 ]; do !!; done

C'est une bonne façon de faire la même chose sans avoir recours à une commande spécifique.

13 votes

Malheureusement, cela ne fonctionne pas pour moi (j'obtiens '!!' command not found). Comment cela est-il censé fonctionner ?

5 votes

C'est une astuce de bash pour exécuter la commande précédente. Par exemple, si vous oubliez d'écrire sudo devant une commande, vous pouvez simplement faire sudo !! pour exécuter la commande précédente avec les privilèges de Root.

1 votes

Puis-je faire un script dans mon profil qui peut faire cela, donc je peux aller : $ makelastwork

112voto

Marc B Points 195501

Vous devez tester $? à la place, qui est l'état de sortie de la commande précédente. passwd sort avec 0 si tout a fonctionné correctement, et avec une valeur non nulle si le changement de mot de passe a échoué (mauvais mot de passe, mot de passe incorrect, etc...).

passwd
while [ $? -ne 0 ]; do
    passwd
done

Avec votre version backtick, vous comparez la sortie de passwd, ce qui donnerait quelque chose comme Enter password y confirm password et autres.

1 votes

J'aime cela parce qu'il est clair comment l'adapter à la situation inverse. Par exemple, exécuter un programme avec un bug non déterministe jusqu'à ce qu'il échoue.

0 votes

Lorsque le succès est indiqué par un code de sortie non nul, c'est ce dont vous avez besoin.

12 votes

Je pense que cela peut être légèrement amélioré en changeant le premier passwd con /bin/false si vous avez une commande longue et compliquée dont vous ne voulez pas conserver deux versions.

10voto

kurumi Points 10096

Vous pouvez utiliser une boucle infinie pour y parvenir :

while true
do
  read -p "Enter password" passwd
  case "$passwd" in
    <some good condition> ) break;;
  esac
done

2 votes

C'est la seule réponse qui ne nécessitait pas de placer ma commande de plusieurs lignes dans une fonction. J'ai fait && break après ma commande de vérification au lieu du cas de sélection.

-2voto

Raghuram Points 2039

Regardez ça. lien et plus particulièrement sur la partie [Sortie conditionnelle de la boucle while avec l'instruction break]. Je ne peux pas essayer le code dans ma boîte maintenant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X