it-swarm.com.ru

Как мне запросить Да / Нет / Отменить ввод в сценарии Linux Shell?

Я хочу приостановить ввод в сценарии Shell и предложить пользователю варианты. Стандартный вопрос типа "Да, Нет или Отмена". Как мне сделать это в типичной командной строке bash?

1273
Myrddin Emrys

Простейшим и наиболее доступным способом получения пользовательского ввода в командной строке является команда read . Лучший способ проиллюстрировать его использование - это простая демонстрация:

while true; do
    read -p "Do you wish to install this program?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

Другой метод, на который указал Стивен Хьюиг, - это команда Bash select . Вот тот же пример, использующий select:

echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) make install; break;;
        No ) exit;;
    esac
done

С select вам не нужно очищать ввод - он отображает доступные варианты, и вы вводите число, соответствующее вашему выбору. Он также выполняет циклы автоматически, поэтому нет необходимости повторять цикл while true, если они дают неверный ввод.

Также, пожалуйста, ознакомьтесь с отличный ответ Ф. Хаури.

1427
Myrddin Emrys

Как минимум пять ответов на один общий вопрос.

В зависимости от

  • posix совместимо: может работать на слабых системах с общими Shell средами
  • bash специфично: используется так называемый bashisms

и если вы хотите

  • простой `` in line '' вопрос/ответ (общие решения)
  • довольно отформатированные интерфейсы, такие как ncurses или более графические, используя libgtk или libqt ...
  • использовать мощные возможности истории чтения строки

1. Общие решения POSIX

Вы можете использовать команду read, а затем if ... then ... else:

echo -n "Is this a good question (y/n)? "
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then
    echo Yes
else
    echo No
fi

(Спасибо комментарий Адама Каца : Заменил тест выше на тот, который более переносим и избегает одного форка :)

POSIX, но особенность одного ключа

Но если вы не хотите, чтобы пользователь нажал ReturnВы могли бы написать:

( Отредактировано: Как справедливо предполагает @JonathanLeffler, сохранение конфигурации stty может быть лучше, чем просто принудить их САНЕ .)

echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Примечание: Это было проверено в sh , bash , ksh , тире и busybox !

То же самое, но в ожидании y или же n:

#/bin/sh
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Использование специальных инструментов

Существует множество инструментов, созданных с использованием libncurses, libgtk, libqt или других графических библиотек. Например, используя whiptail:

if whiptail --yesno "Is this a good question" 20 60 ;then
    echo Yes
else
    echo No
fi

В зависимости от вашей системы вам может потребоваться заменить whiptail другим похожим инструментом:

dialog --yesno "Is this a good question" 20 60 && echo Yes

gdialog --yesno "Is this a good question" 20 60 && echo Yes

kdialog --yesno "Is this a good question" 20 60 && echo Yes

где 20 - высота диалогового окна в количестве строк, а 60 - ширина диалогового окна. Все эти инструменты имеют почти одинаковый синтаксис.

DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...

2. Bash конкретные решения

Основной в строке метод

read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
    y|Y )
        echo Yes
    ;;
    * )
        echo No
    ;;
esac

Я предпочитаю использовать case, чтобы при необходимости я даже смог проверить yes | ja | si | oui ...

в строке с функцией одного ключа

В bash мы можем указать длину предполагаемого ввода для команды read:

read -n 1 -p "Is this a good question (y/n)? " answer

В bash команда read принимает параметр timeout , который может быть полезен.

read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes"  # if 'yes' have to be default choice

Некоторые приемы для специализированных инструментов

Более сложные диалоговые окна, кроме простых yes - no целей:

dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe

Индикатор:

dialog --gauge "Filling the tank" 20 60 0 < <(
    for i in {1..100};do
        printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
        sleep .033
    done
) 

Маленькая демка:

#!/bin/sh
while true ;do
    [ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
    DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
            whiptail       "dialog boxes from Shell scripts" >/dev/tty \
            dialog         "dialog boxes from Shell with ncurses" \
            gdialog        "dialog boxes from Shell with Gtk" \
            kdialog        "dialog boxes from Shell with Kde" ) || exit
    clear;echo "Choosed: $DIALOG."
    for i in `seq 1 100`;do
        date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
        sleep .0125
      done | $DIALOG --gauge "Filling the tank" 20 60 0
    $DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
    sleep 3
    if $DIALOG --yesno  "Do you like this demo?" 20 60 ;then
        AnsYesNo=Yes; else AnsYesNo=No; fi
    AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
    AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
    $DIALOG --textbox /etc/motd 20 60
    AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
        Correct "This demo is useful"        off \
        Fun        "This demo is Nice"        off \
        Strong        "This demo is complex"        on 2>&1 >/dev/tty)
    AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
        " -1" "Downgrade this answer"        off \
        "  0" "Not do anything"                on \
        " +1" "Upgrade this anser"        off 2>&1 >/dev/tty)
    out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
    $DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
  done

Больше образца? Взгляните на используя whiptail для выбора USB-устройства и селектор USB-накопителя: USBKeyChooser

5. Использование истории readline

Пример:

#!/bin/bash

set -i
HISTFILE=~/.myscript.history
history -c
history -r

myread() {
    read -e -p '> ' $1
    history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6

while myread line;do
    case ${line%% *} in
        exit )  break ;;
        *    )  echo "Doing something with '$line'" ;;
      esac
  done

Это создаст файл .myscript.history в вашем каталоге $HOME, чем вы можете использовать команды истории readline, например UpDownCtrl+r и другие.

450
F. Hauri
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
340
Pistos

Вы можете использовать встроенную команду read ; Используйте параметр -p, чтобы запросить у пользователя вопрос.

Начиная с BASH4, теперь вы можете использовать -i, чтобы предложить ответ, поэтому пользователю нужно всего лишь нажать return, чтобы ввести его:

read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH

(Но не забудьте использовать опцию "readline" -e, чтобы разрешить редактирование строки с помощью клавиш со стрелками)

Если вам нужна логика "да/нет", вы можете сделать что-то вроде этого:

read -e -p "
List the content of your home dir ? [Y/n] " YN

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
151
yPhil

Bash имеет выберите для этой цели.

select result in Yes No Cancel
do
    echo $result
done
102
Steven Huwig
read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
  echo "Glad to hear it"
else
  echo "You need more bash programming"
fi
54
serg

Вот что я собрал:

#!/bin/sh

promptyn () {
    while true; do
        read -p "$1 " yn
        case $yn in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

if promptyn "is the sky blue?"; then
    echo "yes"
else
    echo "no"
fi

Я новичок, поэтому возьмите это с крошкой соли, но, похоже, это сработает.

32
mpen
inquire ()  {
  echo  -n "$1 [y/n]? "
  read answer
  finish="-1"
  while [ "$finish" = '-1' ]
  do
    finish="1"
    if [ "$answer" = '' ];
    then
      answer=""
    else
      case $answer in
        y | Y | yes | YES ) answer="y";;
        n | N | no | NO ) answer="n";;
        *) finish="-1";
           echo -n 'Invalid response -- please reenter:';
           read answer;;
       esac
    fi
  done
}

... other stuff

inquire "Install now?"

...
28
SumoRunner

Ты хочешь:

  • Встроенные команды Bash (т.е. переносимые)
  • Проверьте TTY
  • Ответ по умолчанию
  • Тайм-аут
  • Цветной вопрос

Отрывок

do_xxxx=y                      # In batch mode => Default is Yes
[[ -t 0 ]] &&                  # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx  # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]]  # Do if 'y' or 'Y' or empty
then
    xxxx
fi

Пояснения

  • [[ -t 0 ]] && read ... => Вызовите команду read если TTY
  • read -n 1 => Ждать одного символа
  • $'\e[1;32m ... \e[0m ' => Печать зеленым цветом
    (зеленый - хорошо, потому что читается на белом/черном фоне)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => регулярное выражение bash

Тайм-аут => Ответ по умолчанию - Нет

do_xxxx=y
[[ -t 0 ]] && {                   # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx ||  # read 'fails' on timeout
do_xxxx=n ; }                     # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
    xxxx
fi
25
olibre

Самый простой способ добиться этого с наименьшим количеством строк заключается в следующем:

read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;

if [ "$CONDITION" == "y" ]; then
   # do something here!
fi

if является лишь примером: вам решать, как обращаться с этой переменной.

21
Apurv Nerlekar

Используйте команду read:

echo Would you like to install? "(Y or N)"

read x

# now check if $x is "y"
if [ "$x" = "y" ]; then
    # do something here!
fi

а затем все остальные вещи, которые вам нужны

17
ThatLinuxGuy

Это решение читает один символ и вызывает функцию с ответом "да".

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi
17
Dennis
read -e -p "Enter your choice: " choice

Параметр -e позволяет пользователю редактировать ввод с помощью клавиш со стрелками.

Если вы хотите использовать предложение в качестве входных данных:

read -e -i "yes" -p "Enter your choice: " choice

Параметр -i выводит подсказки.

12
Jahid

Извините за публикацию на такой старый пост. Несколько недель назад я столкнулся с подобной проблемой, в моем случае мне нужно было решение, которое также работало в онлайн-установочном скрипте, например: curl -Ss https://raw.github.com/_____/installer.sh | bash

Использование read yesno < /dev/tty прекрасно работает для меня:

echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty

if [ "x$yesno" = "xy" ];then

   # Yes
else

   # No
fi

Надеюсь, это кому-нибудь поможет.

10
user1183098

Чтобы получить поле ввода, похожее на ncurses, используйте диалог вот так:

#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then 
    echo "Let's do something risky"
    # do something risky
else 
    echo "Let's stay boring"
fi

Диалоговый пакет устанавливается по умолчанию как минимум в SUSE Linux.

8
Thorsten Staerk

Вы можете использовать значение по умолчанию REPLY для read, преобразовать его в нижний регистр и сравнить с набором переменных с выражением.
Скрипт также поддерживает ja/si/oui

read -rp "Do you want a demo? [y/n/c] "

[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }

if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
   echo "Positive"
fi
7
Walter A

Только одно нажатие

Вот более длинный, но многократно используемый и модульный подход:

  • Возвращает 0 = да и 1 = нет
  • Не нужно нажимать ввод - только один символ
  • Может нажать enter принять выбор по умолчанию
  • Можно отключить выбор по умолчанию для принудительного выбора
  • Работает как для zsh, так и bash.

По умолчанию "нет" при нажатии Enter

Обратите внимание, что N пишется с заглавной буквы. Здесь нажимается ввод, принимая значение по умолчанию:

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?

Также обратите внимание, что [y/N]? был автоматически добавлен. По умолчанию "нет" принимается, поэтому ничего не отображается.

Повторять запрос до получения правильного ответа:

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *

По умолчанию "да" при нажатии Enter

Обратите внимание, что Y пишется с большой буквы:

$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *

Выше я просто нажал Enter, поэтому команда запустилась.

Нет по умолчанию на enter - требуется y или n

$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1

Здесь был возвращен 1 или false. Обратите внимание, что с помощью этой функции более низкого уровня вам нужно будет предоставить собственную подсказку [y/n]?.

Код

# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
  local REPLY IFS=
  >/dev/tty printf '%s' "$*"
  [[ $ZSH_VERSION ]] && read -rk1  # Use -u0 to read from STDIN
  # See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
  [[ $BASH_VERSION ]] && </dev/tty read -rn1
  printf '%s' "$REPLY"
}

# Get a y/n from the user, return yes=0, no=1 enter=$2
# Prompt using $1.
# If set, return $2 on pressing enter, useful for cancel or defualting
function get_yes_keypress {
  local Prompt="${1:-Are you sure [y/n]? }"
  local enter_return=$2
  local REPLY
  # [[ ! $Prompt ]] && Prompt="[y/n]? "
  while REPLY=$(get_keypress "$Prompt"); do
    [[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
    case "$REPLY" in
      Y|y)  return 0;;
      N|n)  return 1;;
      '')   [[ $enter_return ]] && return "$enter_return"
    esac
  done
}

# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
  local Prompt="${*:-Are you sure} [y/N]? "
  get_yes_keypress "$Prompt" 1
}    

# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
  local Prompt="${*:-Are you sure} [Y/n]? "
  get_yes_keypress "$Prompt" 0
}
6
Tom Hale

Я заметил, что никто не опубликовал ответ, показывающий многострочное эхо-меню для такого простого пользовательского ввода, так что вот мой выбор

#!/bin/bash

function ask_user() {    

echo -e "
#~~~~~~~~~~~~#
| 1.) Yes    |
| 2.) No     |
| 3.) Quit   |
#~~~~~~~~~~~~#\n"

read -e -p "Select 1: " choice

if [ "$choice" == "1" ]; then

    do_something

Elif [ "$choice" == "2" ]; then

    do_something_else

Elif [ "$choice" == "3" ]; then

    clear && exit 0

else

    echo "Please select 1, 2, or 3." && sleep 3
    clear && ask_user

fi
}

ask_user

Этот метод был опубликован в надежде, что кто-то найдет его полезным и экономящим время.

4
Yokai

Вариант с множественным выбором:

ask () {                        # $1=question $2=options
    # set REPLY
    # options: x=..|y=..
    while $(true); do
        printf '%s [%s] ' "$1" "$2"
        stty cbreak
        REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
        stty -cbreak
        test "$REPLY" != "$(printf '\n')" && printf '\n'
        (
            IFS='|'
            for o in $2; do
                if [ "$REPLY" = "${o%%=*}" ]; then
                    printf '\n'
                    break
                fi
            done
        ) | grep ^ > /dev/null && return
    done
}

Пример:

$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$

Он установит REPLY в y (внутри скрипта).

4
Ernest A

Вдохновленный ответами @Mark и @Myrddin, я создал эту функцию для универсальной подсказки.

uniprompt(){
    while true; do
        echo -e "$1\c"
        read opt
        array=($2)
        case "${array[@]}" in  *"$opt"*) eval "$3=$opt";return 0;; esac
        echo -e "$opt is not a correct value\n"
    done
}

используйте это так:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
4
poxtron

Один простой способ сделать это с помощью xargs -p или gnu parallel --interactive.

Мне нравится поведение xargs немного лучше, потому что оно выполняет каждую команду сразу после запроса, как и другие интерактивные команды Unix, вместо того, чтобы собирать дачи для запуска в конце. (Вы можете нажать Ctrl-C после того, как пройдете те, которые вы хотели.)

например.,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/
3
Joshua Goldberg

Я предлагаю вам используйте диалог ...

Ученик Linux: улучшите сценарии оболочки Bash с помощью диалога

Команда dialog позволяет использовать оконные блоки в сценариях Shell, чтобы сделать их использование более интерактивным.

он прост и удобен в использовании, также есть версия gnome под названием gdialog, которая принимает те же параметры, но показывает стиль GUI на X.

3
Osama Al-Maadeed

более общим будет:

function menu(){
    title="Question time"
    Prompt="Select:"
    options=("Yes" "No" "Maybe")
    echo "$title"
    PS3="$Prompt"
    select opt in "${options[@]}" "Quit/Cancel"; do
        case "$REPLY" in
            1 ) echo "You picked $opt which is option $REPLY";;
            2 ) echo "You picked $opt which is option $REPLY";;
            3 ) echo "You picked $opt which is option $REPLY";;
            $(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
            *) echo "Invalid option. Try another one.";continue;;
         esac
     done
     return
}
3
Alexander Löfqvist

В качестве друга однострочной команды я использовал следующее:

while [ -z $Prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) Prompt=true; break;; n|N ) exit 0;; esac; done; Prompt=;

Написано longform, оно работает так:

while [ -z $Prompt ];
  do read -p "Continue (y/n)?" choice;
  case "$choice" in
    y|Y ) Prompt=true; break;;
    n|N ) exit 0;;
  esac;
done;
Prompt=;
2
ccDict

В таком сценарии я пару раз использовал оператор case, и для этого достаточно использовать регистр дел. Цикл while, который экранирует блок case, который использует логическое условие, может быть реализован для того, чтобы сохранить еще больший контроль над программой и выполнить многие другие требования. После того как все условия будут выполнены, можно использовать break, который передаст управление основной части программы. Кроме того, для удовлетворения других условий, конечно, могут быть добавлены условные операторы, сопровождающие управляющие структуры: оператор case и возможный цикл while.

Пример использования оператора case для выполнения вашего запроса

#! /bin/sh 

# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-Shell, e.g. /bin/sh

# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input 
# of the Prompt in a case statement (case control structure), 

echo Would you like us to perform the option: "(Y|N)"

read inPut

case $inPut in
    # echoing a command encapsulated by 
    # backticks (``) executes the command
    "Y") echo `Do something crazy`
    ;;
    # depending on the scenario, execute the other option
    # or leave as default
    "N") echo `execute another option`
    ;;
esac

exit
2
oOpSgEo
yn() {
  if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
  then eval $1;
  else eval $2;
  fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'
2
jlettvin

В ответ на других:

Вам не нужно указывать регистр в BASH4, просто используйте ",", чтобы сделать переменную в нижнем регистре. Также я очень не люблю помещать код внутри блока чтения, получать результат и иметь дело с ним вне IMO блока чтения. Также добавьте "q" для выхода из IMO. И наконец, почему введите "да", просто используйте -n1 и нажмите клавишу y.

Пример: пользователь может нажать y/n, а также q, чтобы просто выйти.

ans=''
while true; do
    read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
    case ${ans,,} in
        y|n|q) break;;
        *) echo "Answer y for yes / n for no  or q for quit.";;
    esac
done

echo -e "\nAnswer = $ans"

if [[ "${ans,,}" == "q" ]] ; then
        echo "OK Quitting, we will assume that he is"
        exit 0
fi

if [[ "${ans,,}" == "y" ]] ; then
        echo "MikeQ is the greatest!!"
else
        echo "No? MikeQ is not the greatest?"
fi
1
Mike Q

Да/Нет/Отмена

Функция

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=''

  echo -n "> $message (Yes/No/Cancel) " >&2

  while [ -z "$result" ] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result='Y' ;;
      n|N ) result='N' ;;
      c|C ) result='C' ;;
    esac
  done

  echo $result
}

Использование

case $(@confirm 'Confirm?') in
  Y ) echo "Yes" ;;
  N ) echo "No" ;;
  C ) echo "Cancel" ;;
esac

Подтвердите с помощью чистого ввода пользователя

Функция

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=3

  echo -n "> $message (y/n) " >&2

  while [[ $result -gt 1 ]] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result=0 ;;
      n|N ) result=1 ;;
    esac
  done

  return $result
}

Использование

if @confirm 'Confirm?' ; then
  echo "Yes"
else
  echo "No"
fi
1
Eduardo Cuomo