How do I prompt for Yes/No/Cancel input in a Linux shell script?

后端 未结 30 2321
不思量自难忘°
不思量自难忘° 2020-11-22 04:52

I want to pause input in a shell script, and prompt the user for choices.
The standard Yes, No, or Cancel type question.
How d

30条回答
  •  清歌不尽
    2020-11-22 05:27

    Single keypress only

    Here's a longer, but reusable and modular approach:

    • Returns 0=yes and 1=no
    • No pressing enter required - just a single character
    • Can press enter to accept the default choice
    • Can disable default choice to force a selection
    • Works for both zsh and bash.

    Defaulting to "no" when pressing enter

    Note that the N is capitalsed. Here enter is pressed, accepting the default:

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

    Also note, that [y/N]? was automatically appended. The default "no" is accepted, so nothing is echoed.

    Re-prompt until a valid response is given:

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

    Defaulting to "yes" when pressing enter

    Note that the Y is capitalised:

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

    Above, I just pressed enter, so the command ran.

    No default on enter - require y or 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
    

    Here, 1 or false was returned. Note that with this lower-level function you'll need to provide your own [y/n]? prompt.

    Code

    # 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 ]] && 
    # 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 
    function confirm_yes {
      local prompt="${*:-Are you sure} [Y/n]? "
      get_yes_keypress "$prompt" 0
    }
    

提交回复
热议问题