82

Edit:

Seems to work within bash. It appears the problem is related to zsh. If there is a better site to post this issue on let me know.


I am writing a simple script that creates a series of directories. I want the user to give a confirmation before I do so. I'm using the following as a basis, but cannot seem to get it to run within a bash function. If I put it outside of a function it works fine. Here is an isolated example:

read.sh

#!/bin/bash
test() {
  read -p "Here be dragons. Continue?" -n 1 -r
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    echo "You asked for it..."
  fi
}

code from this SO post.

Sourcing the file and/or test results in the following error: read:1: -p: no coprocess. Same output when I place it in my .bashrc

Edit::

@hennes

  1. I want the function to be in a config file, so I can call it from whatever directory (ideally my .bashrc or .zshrc)
  2. I've corrected the formatting of the first commented line. Problem still exists in zsh
  3. Bash version is 3.2, but you've helped me figure out that the problem is with zsh and not bash.
Nick Tomlin
  • 1,157

3 Answers3

128

The –p option doesn’t mean the same thing to bash’s read built-in command and zsh’s read built-in command.  In zsh’s read command, –p means –– guess –– “Input is read from the coprocess.”  I suggest that you display your prompt with echo or printf.

You may also need to replace –n 1 with –k or –k 1.


The zsh equivalent of bash's read -p prompt is

read "?Here be dragons. Continue?"

Anything after a ? in the first argument is used as the prompt string.

And of course you can specify a variable name to read into (and this may be better style):

read "brave?Here be dragons. Continue?"
if [[ "$brave" =~ ^[Yy]$ ]]
then
    ...
fi

(Quoting shell variables is generally a good idea, too.)

13

This code seems to do what you want in zsh.
(Note that the question you refered to explicitly mentions it is for bash).

#!/usr/bin/env zsh

test() { echo -n "Here be dragons. Continue?" read REPLY

if [[ $REPLY =~ ^[Yy]$ ]] then echo "You asked for it..." fi }

test

Three comments:

alper
  • 200
Hennes
  • 65,804
  • 7
  • 115
  • 169
5

This version allows you to have more than one case y or Y, n or N

  1. Optionally: Repeat the question until an approve question is provided

  2. Optionally: Ignore any other answer

  3. Optionally: Exit the terminal if you want

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) echo 'nope n' ;;
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }
    

Notice this too: On the last line of this function clear the REPLY variable. Otherwise if you echo $REPLY you will see it is still set until you open or close your terminal or set it again.