Як можна запускати команду в bash over до успіху


237

У мене є сценарій і хочу попросити у користувача деяку інформацію, сценарій не може продовжуватися, поки користувач не заповнить цю інформацію. Далі йде моя спроба ввести команду в цикл, щоб досягти цього, але це чомусь не працює.

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

Я спробував багато варіантів циклу while:

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

Але я не можу, здається, змусити його працювати.

Відповіді:


403
until passwd
do
  echo "Try again"
done

або

while ! passwd
do
  echo "Try again"
done

20
З цього важко Ctrl-C.
DonGar

Якщо ви думаєте, що вам потрібно буде скасувати це, просто відкрийте новий екземпляр своєї оболонки (наприклад, введіть "bash") і, коли ви хочете скасувати її, перейдіть в інше вікно терміналу і вбийте щойно породжений bash процес.
Етан

50
З цього легко Ctr-C: until passwd; do echo "Try again"; sleep 2; done- все, що вам потрібно зробити, це натиснути Ctr-C відразу після (протягом двох секунд), що echoзробив це.
Крістіан

9
@azmeuk: Спробуйте щось на кшталт until passwd || (( count++ >= 5 )); do echo "foo"; done(тільки баш, переконайтеся, що встановити кількість до 0, якщо така варабельність існує) Якщо вам це потрібно для звичайного ш, збільште лічильник в тілі і використовуйте []
Джастін Сане

2
Посилаючись на цю сторінку багато разів, я вирішив створити загальну функцію bash для повторних команд, ось вона: gist.github.com/felipou/6fbec22c4e04d3adfae5
felipou

94

$?Натомість вам потрібно протестувати , що є статусом виходу попередньої команди. passwdзакінчується з 0, якщо все працювало нормально, і не нульовим, якщо зміна passwd не вдалася (неправильний пароль, невідповідність пароля тощо)

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

З вашою версією backtick ви порівнюєте вихід passwd, який би був подібним Enter passwordі confirm passwordподібним.


2
Чи не повинно бути це $??
Шон Чін

Мені це подобається, бо зрозуміло, як адаптувати його до протилежної ситуації. наприклад, запускайте програму з недетермінованою помилкою, поки вона не завершиться
Ерік

Коли успіх вказується ненульовим кодом виходу, саме це вам потрібно.
Гудлаугур Егільссон

2
Я думаю , що це може бути трохи покращено шляхом зміни першого passwdз , /bin/falseякщо у вас є якась - то довге і складне команда , яку ви не хочете , щоб тримати дві версії.
coladict

Повинна бути прийнята відповідь imho. Це має працювати в більшості оболонок (тестується в bash, mksh та золі) і легко адаптується до ситуації.
linuxandria

73

Щоб детальніше розповісти про відповідь @Marc B,

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

Це приємний спосіб робити те саме, що не визначено командою.


11
На жаль, для мене не працює (я отримую команду "!!" не знайдено). Як це має працювати?
Йоханнес Рудольф

2
Це баш-трюк для запуску попередньої команди. Наприклад, якщо ви забудете написати sudoперед командою, ви можете просто виконати sudo !!попередню команду з правами root.
JohnEye

1
Чи можу я створити сценарій у своєму профілі, який може це зробити, тому я можу перейти: $ makelastwork
user230910

2
Як спати між пробіжками?
Каміль Дзедзіч

6

Для цього можна використовувати нескінченну петлю:

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

2
Це єдина відповідь, яка не вимагала введення моєї багаторядкової команди у функцію. Я зробив && breakпісля команди перевірки, хоча замість вибору.
carlin.scott

4

Якщо хтось бажає мати обмеження для повторного спроби:

max_retry=5
counter=0
until $command
do
   sleep 1
   [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
   echo "Trying again. Try #$counter"
   ((counter++))
done

1
until $(command)в основному завжди помиляється. Використовуйте until commandзамість цього. $(...)Викликає вихід з commandбути сам по собі працювати в якості команди, а статус виходу цієї вторинної команди , щоб бути тим, що петля вирішує бігти або не далі за; це тільки якщо НЕ буде не стандартний висновок про те , що статус виходу з самої команди вважається , коли заміна команди присутній.
Чарльз Даффі

$commandтакож не є чудовим заповнювачем місця - див. BashFAQ # 50 про те, чому використання рядків для зберігання команд не є надійним. Все-таки це краще, ніж було; downvote втягнутий.
Чарльз Даффі

3
while [ -n $(passwd) ]; do
        echo "Try again";
done;

3
Це не так, як це зробити ... ви нехтуєте stdout psswd і потім робите одинарний тест на ньому. @duckworthd - це добре.
Рей Фосс

Більше того, оскільки немає цитування, тест буде неправильно поводитись, коли є вихід, але це більше ніж одне слово, або це вираження глобула, що відповідає файлам у поточному каталозі тощо.
Чарльз Даффі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.