In Bash, how to add “Are you sure [Y/n]” to any command or alias?

前端 未结 17 2951
轮回少年
轮回少年 2020-11-29 15:11

In this particular case, I\'d like to add a confirm in Bash for

Are you sure? [Y/n]

for Mercurial\'s hg push ssh://username@www.example.com//some

17条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-29 15:13

    No pressing enter required

    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"
    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 no capitalisation in [y/n]?

    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
    }
    

提交回复
热议问题